Search in sources :

Example 1 with ExpiredJWTException

use of io.gravitee.am.common.exception.jwt.ExpiredJWTException in project gravitee-access-management by gravitee-io.

the class DefaultJWTParser method parse.

@Override
public JWT parse(String payload) {
    try {
        // verify format
        SignedJWT signedJWT = SignedJWT.parse(payload);
        // verify signature
        boolean verified = signedJWT.verify(verifier);
        if (!verified) {
            throw new JOSEException("The signature was not verified");
        }
        Map<String, Object> claims = signedJWT.getPayload().toJSONObject().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        JWT jwt = new JWT(claims);
        // verify exp and nbf values
        // https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-30#section-4.1.4
        // token MUST NOT be accepted on or after any specified exp time
        Instant now = Instant.now();
        evaluateExp(jwt.getExp(), now, this.allowedClockSkewMillis);
        // https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-30#section-4.1.5
        // token MUST NOT be accepted before any specified nbf time
        evaluateNbf(jwt.getNbf(), now, this.allowedClockSkewMillis);
        return jwt;
    } catch (ParseException ex) {
        logger.debug("The following JWT token : {} is malformed", payload);
        throw new MalformedJWTException("Token is malformed", ex);
    } catch (ExpiredJWTException ex) {
        logger.debug("The following JWT token : {} is expired", payload);
        throw new ExpiredJWTException("Token is expired", ex);
    } catch (PrematureJWTException ex) {
        logger.debug("The following JWT token : {} must not be accepted (nbf)", payload);
        throw new PrematureJWTException("Token must not be accepted (nbf)", ex);
    } catch (JOSEException ex) {
        logger.debug("Verifying JWT token signature : {} has failed", payload);
        throw new SignatureException("Token's signature is invalid", ex);
    } catch (Exception ex) {
        logger.error("An error occurs while parsing JWT token : {}", payload, ex);
        throw ex;
    }
}
Also used : JWT(io.gravitee.am.common.jwt.JWT) SignedJWT(com.nimbusds.jwt.SignedJWT) Instant(java.time.Instant) PrematureJWTException(io.gravitee.am.common.exception.jwt.PrematureJWTException) ExpiredJWTException(io.gravitee.am.common.exception.jwt.ExpiredJWTException) SignedJWT(com.nimbusds.jwt.SignedJWT) SignatureException(io.gravitee.am.common.exception.jwt.SignatureException) JOSEException(com.nimbusds.jose.JOSEException) MalformedJWTException(io.gravitee.am.common.exception.jwt.MalformedJWTException) ExpiredJWTException(io.gravitee.am.common.exception.jwt.ExpiredJWTException) PrematureJWTException(io.gravitee.am.common.exception.jwt.PrematureJWTException) InvalidKeyException(java.security.InvalidKeyException) SignatureException(io.gravitee.am.common.exception.jwt.SignatureException) ParseException(java.text.ParseException) MalformedJWTException(io.gravitee.am.common.exception.jwt.MalformedJWTException) ParseException(java.text.ParseException) JOSEException(com.nimbusds.jose.JOSEException) Map(java.util.Map)

Example 2 with ExpiredJWTException

use of io.gravitee.am.common.exception.jwt.ExpiredJWTException in project gravitee-access-management by gravitee-io.

the class AuthenticationRequestParseRequestObjectHandler method validateRequestObjectClaims.

private Single<JWT> validateRequestObjectClaims(RoutingContext context, JWT jwt) {
    try {
        OpenIDProviderMetadata oidcMeta = context.get(PROVIDER_METADATA_CONTEXT_KEY);
        Client client = context.get(CLIENT_CONTEXT_KEY);
        final JWTClaimsSet claims = jwt.getJWTClaimsSet();
        // aud : The Audience claim MUST contain the value of the Issuer Identifier for the OP, which identifies the Authorization Server as an intended audience.
        final Object aud = claims.getClaim(Claims.aud);
        if (aud == null || (aud instanceof String && !oidcMeta.getIssuer().equals(aud)) || (aud instanceof Collection && (((Collection) aud).isEmpty() || !((Collection) aud).stream().anyMatch(oidcMeta.getIssuer()::equals)))) {
            return Single.error(new InvalidRequestException("aud is missing or invalid"));
        }
        // iss : The Issuer claim MUST be the client_id of the OAuth Client.
        final String iss = claims.getStringClaim(Claims.iss);
        if (iss == null || !client.getClientId().equals(iss)) {
            return Single.error(new InvalidRequestException("iss is missing or invalid"));
        }
        // exp : An expiration time that limits the validity lifetime of the signed authentication request.
        final Date exp = claims.getDateClaim(Claims.exp);
        if (exp == null) {
            return Single.error(new InvalidRequestException("exp is missing"));
        }
        DefaultJWTParser.evaluateExp(exp.getTime() / 1000, Instant.now(), 0);
        // iat : The time at which the signed authentication request was created.
        final Date iat = claims.getDateClaim(Claims.iat);
        if (iat == null) {
            return Single.error(new InvalidRequestException("iat is missing"));
        }
        // nbf : The time before which the signed authentication request is unacceptable.
        final Date nbf = claims.getDateClaim(Claims.nbf);
        if (nbf == null) {
            return Single.error(new InvalidRequestException("nbf is missing"));
        }
        DefaultJWTParser.evaluateNbf(nbf.getTime() / 1000, Instant.now(), 0);
        // jti : A unique identifier for the signed authentication request.
        if (claims.getStringClaim(Claims.jti) == null) {
            return Single.error(new InvalidRequestException("jti is missing"));
        }
    } catch (ParseException e) {
        return Single.error(new InvalidRequestException("Unable to read claims in the request parameter"));
    } catch (PrematureJWTException e) {
        return Single.error(new InvalidRequestException("nbf is invalid"));
    } catch (ExpiredJWTException e) {
        return Single.error(new InvalidRequestException("jwt has expired"));
    }
    return Single.just(jwt);
}
Also used : JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) PrematureJWTException(io.gravitee.am.common.exception.jwt.PrematureJWTException) ExpiredJWTException(io.gravitee.am.common.exception.jwt.ExpiredJWTException) Collection(java.util.Collection) OpenIDProviderMetadata(io.gravitee.am.gateway.handler.oidc.service.discovery.OpenIDProviderMetadata) InvalidRequestException(io.gravitee.am.common.exception.oauth2.InvalidRequestException) ParseException(java.text.ParseException) Client(io.gravitee.am.model.oidc.Client) Date(java.util.Date)

Example 3 with ExpiredJWTException

use of io.gravitee.am.common.exception.jwt.ExpiredJWTException in project gravitee-access-management by gravitee-io.

the class DefaultJWTParser method evaluateExp.

/**
 * Throw {@link ExpiredJWTException} if exp is after now
 *
 * @param exp
 * @param now
 */
public static void evaluateExp(long exp, Instant now, long clockSkew) {
    if (exp > 0) {
        Instant expInstant = Instant.ofEpochSecond(exp);
        if (now.isAfter(expInstant)) {
            long differenceMillis = now.toEpochMilli() - expInstant.toEpochMilli();
            String msg = "JWT expired at " + expInstant + ". Current time: " + now + ", a difference of " + differenceMillis + " milliseconds.  Allowed clock skew: " + clockSkew + " milliseconds.";
            throw new ExpiredJWTException(msg);
        }
    }
}
Also used : Instant(java.time.Instant) ExpiredJWTException(io.gravitee.am.common.exception.jwt.ExpiredJWTException)

Example 4 with ExpiredJWTException

use of io.gravitee.am.common.exception.jwt.ExpiredJWTException in project gravitee-access-management by gravitee-io.

the class CibaAuthenticationRequestResolver method validateLoginHintToken.

private Single<CibaAuthenticationRequest> validateLoginHintToken(CibaAuthenticationRequest authRequest, JWT jwt) {
    try {
        final Date expirationTime = jwt.getJWTClaimsSet().getExpirationTime();
        if (expirationTime != null) {
            evaluateExp(expirationTime.toInstant().getEpochSecond(), Instant.now(), 0);
        }
        final JSONObject subIdObject = jwt.getJWTClaimsSet().getJSONObjectClaim("sub_id");
        /*
                sub_id is an object specifying the field identifying the user (through format entry)
                Supported format : email and username
                {
                  "sub_id": {
                    "format": "email",
                    "email": "user@acme.fr"
                  }
                }
             */
        final FilterCriteria criteria = new FilterCriteria();
        criteria.setQuoteFilterValue(false);
        final String field = subIdObject.getAsString("format");
        if (!"email".equals(field) && !"username".equals(field)) {
            return Single.error(new InvalidRequestException("Invalid hint, only email and username are supported"));
        }
        criteria.setFilterName(field);
        criteria.setFilterValue(subIdObject.getAsString(field));
        return userService.findByDomainAndCriteria(domain.getId(), criteria).flatMap(users -> {
            if (users.size() != 1) {
                LOGGER.warn("login_hint_token match multiple users or no one");
                return Single.error(new InvalidRequestException("Invalid hint"));
            }
            authRequest.setSubject(users.get(0).getId());
            return Single.just(authRequest);
        });
    } catch (ExpiredJWTException e) {
        return Single.error(new ExpiredLoginHintTokenException("login_token_hint expired"));
    } catch (ParseException e) {
        // should never happen
        LOGGER.warn("login_hint_token can't be read", e);
        return Single.error(new ExpiredLoginHintTokenException("invalid login_token_hint"));
    }
}
Also used : JSONObject(net.minidev.json.JSONObject) ExpiredLoginHintTokenException(io.gravitee.am.common.exception.oauth2.ExpiredLoginHintTokenException) ExpiredJWTException(io.gravitee.am.common.exception.jwt.ExpiredJWTException) InvalidRequestException(io.gravitee.am.common.exception.oauth2.InvalidRequestException) FilterCriteria(io.gravitee.am.repository.management.api.search.FilterCriteria) ParseException(java.text.ParseException) Date(java.util.Date)

Aggregations

ExpiredJWTException (io.gravitee.am.common.exception.jwt.ExpiredJWTException)4 ParseException (java.text.ParseException)3 PrematureJWTException (io.gravitee.am.common.exception.jwt.PrematureJWTException)2 InvalidRequestException (io.gravitee.am.common.exception.oauth2.InvalidRequestException)2 Instant (java.time.Instant)2 Date (java.util.Date)2 JOSEException (com.nimbusds.jose.JOSEException)1 JWTClaimsSet (com.nimbusds.jwt.JWTClaimsSet)1 SignedJWT (com.nimbusds.jwt.SignedJWT)1 MalformedJWTException (io.gravitee.am.common.exception.jwt.MalformedJWTException)1 SignatureException (io.gravitee.am.common.exception.jwt.SignatureException)1 ExpiredLoginHintTokenException (io.gravitee.am.common.exception.oauth2.ExpiredLoginHintTokenException)1 JWT (io.gravitee.am.common.jwt.JWT)1 OpenIDProviderMetadata (io.gravitee.am.gateway.handler.oidc.service.discovery.OpenIDProviderMetadata)1 Client (io.gravitee.am.model.oidc.Client)1 FilterCriteria (io.gravitee.am.repository.management.api.search.FilterCriteria)1 InvalidKeyException (java.security.InvalidKeyException)1 Collection (java.util.Collection)1 Map (java.util.Map)1 JSONObject (net.minidev.json.JSONObject)1