package com.jetdrone.vertx.yoke.middleware;

import com.jetdrone.vertx.yoke.Middleware;
import com.jetdrone.vertx.yoke.core.YokeException;
import org.jetbrains.annotations.NotNull;
import org.vertx.java.core.Handler;

import java.util.regex.Pattern;

public class JWT extends Middleware {

    private static final Pattern BEARER = Pattern.compile("^Bearer$", Pattern.CASE_INSENSITIVE);

    private final String skip;
    private final com.jetdrone.vertx.yoke.util.JWT jwt;

    public JWT(@NotNull String secret) {
        this(secret, null);
    }

    public JWT(@NotNull String secret, String skip) {
        this.skip = skip;
        this.jwt = new com.jetdrone.vertx.yoke.util.JWT(secret);
    }

    @Override
    public void handle(@NotNull final YokeRequest request, @NotNull final Handler<Object> next) {
        String token = null;

        if ("OPTIONS".equals(request.method()) && request.getHeader("access-control-request-headers") != null) {
            for (String ctrlReq : request.getHeader("access-control-request-headers").split(",")) {
                if (ctrlReq.contains("authorization")) {
                    next.handle(null);
                    return;
                }
            }
        }

        if (skip != null && skip.contains(request.normalizedPath())) {
            next.handle(null);
            return;
        }

        final String authorization = request.getHeader("authorization");

        if (authorization != null) {
            String[] parts = authorization.split(" ");
            if (parts.length == 2) {
                final String scheme = parts[0],
                             credentials = parts[1];

                if (BEARER.matcher(scheme).matches()) {
                    token = credentials;
                }
            } else {
                next.handle(new YokeException(401, "Format is Authorization: Bearer [token]"));
                return;
            }
        } else {
            next.handle(new YokeException(401, "No Authorization header was found"));
            return;
        }

        try {
            request.put("jwt", jwt.decode(token));
            next.handle(null);
        } catch (RuntimeException e) {
            next.handle(new YokeException(401, e));
        }
    }
}

@@ -209,16 +209,60 @@
 Handler;
+%0Aimport org.vertx.java.core.json.JsonObject;
 %0A%0Aimport
@@ -2119,16 +2119,1087 @@
   try %7B%0A
+            final JsonObject jwtToken = jwt.decode(token);%0A%0A            final long now = System.currentTimeMillis();%0A%0A            if (jwtToken.containsField(%22iat%22)) %7B%0A                Long iat = jwtToken.getLong(%22iat%22);%0A                // issue at must be in the past%0A                if (iat %3E= now) %7B%0A                    next.handle(new YokeException(401, %22Invalid Token!%22));%0A                    return;%0A                %7D%0A            %7D%0A%0A            if (jwtToken.containsField(%22nbf%22)) %7B%0A                Long nbf = jwtToken.getLong(%22nbf%22);%0A                // not before must be after now%0A                if (nbf %3E= now) %7B%0A                    next.handle(new YokeException(401, %22Invalid Token!%22));%0A                    return;%0A                %7D%0A            %7D%0A%0A            if (jwtToken.containsField(%22exp%22)) %7B%0A                Long exp = jwtToken.getLong(%22exp%22);%0A                // expires must be after now%0A                if (exp %3E= now) %7B%0A                    next.handle(new YokeException(401, %22Invalid Token!%22));%0A                    return;%0A                %7D%0A            %7D%0A
         

validate registered claims