use of io.gravitee.am.common.exception.jwt.PrematureJWTException 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;
}
}
use of io.gravitee.am.common.exception.jwt.PrematureJWTException 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);
}
use of io.gravitee.am.common.exception.jwt.PrematureJWTException in project gravitee-access-management by gravitee-io.
the class DefaultJWTParser method evaluateNbf.
/**
* Throw {@link ExpiredJWTException} if now is before nbf
*
* @param nbf
* @param now
*/
public static void evaluateNbf(long nbf, Instant now, long clockSkew) {
if (nbf > 0) {
Instant nbfInstant = Instant.ofEpochSecond(nbf);
if (now.isBefore(nbfInstant)) {
long differenceMillis = nbfInstant.toEpochMilli() - now.toEpochMilli();
String msg = "JWT must not be accepted before " + nbfInstant + ". Current time: " + now + ", a difference of " + differenceMillis + " milliseconds. Allowed clock skew: " + clockSkew + " milliseconds.";
throw new PrematureJWTException(msg);
}
}
}
Aggregations