use of org.jose4j.jwt.NumericDate in project blueocean-plugin by jenkinsci.
the class JwtAuthenticationToken method validate.
private static JwtClaims validate(StaplerRequest request) {
String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
throw new ServiceException.UnauthorizedException("JWT token not found");
}
String token = authHeader.substring("Bearer ".length());
try {
JsonWebStructure jws = JsonWebStructure.fromCompactSerialization(token);
String alg = jws.getAlgorithmHeaderValue();
if (alg == null || !alg.equals(RSA_USING_SHA256)) {
logger.error(String.format("Invalid JWT token: unsupported algorithm in header, found %s, expected %s", alg, RSA_USING_SHA256));
throw new ServiceException.UnauthorizedException("Invalid JWT token");
}
String kid = jws.getKeyIdHeaderValue();
if (kid == null) {
logger.error("Invalid JWT token: missing kid");
throw new ServiceException.UnauthorizedException("Invalid JWT token");
}
JwtToken.JwtRsaDigitalSignatureKey key = new JwtToken.JwtRsaDigitalSignatureKey(kid);
try {
if (!key.exists()) {
throw new ServiceException.NotFoundException(String.format("kid %s not found", kid));
}
} catch (IOException e) {
logger.error(String.format("Error reading RSA key for id %s: %s", kid, e.getMessage()), e);
throw new ServiceException.UnexpectedErrorException("Unexpected error: " + e.getMessage(), e);
}
JwtConsumer jwtConsumer = new JwtConsumerBuilder().setRequireExpirationTime().setRequireJwtId().setAllowedClockSkewInSeconds(// allow some leeway in validating time based claims to account for clock skew
30).setRequireSubject().setVerificationKey(// verify the sign with the public key
key.getPublicKey()).build();
try {
JwtContext context = jwtConsumer.process(token);
JwtClaims claims = context.getJwtClaims();
//check if token expired
NumericDate expirationTime = claims.getExpirationTime();
if (expirationTime.isBefore(NumericDate.now())) {
throw new ServiceException.UnauthorizedException("Invalid JWT token: expired");
}
return claims;
} catch (InvalidJwtException e) {
logger.error("Invalid JWT token: " + e.getMessage(), e);
throw new ServiceException.UnauthorizedException("Invalid JWT token");
} catch (MalformedClaimException e) {
logger.error(String.format("Error reading sub header for token %s", jws.getPayload()), e);
throw new ServiceException.UnauthorizedException("Invalid JWT token: malformed claim");
}
} catch (JoseException e) {
logger.error("Error parsing JWT token: " + e.getMessage(), e);
throw new ServiceException.UnauthorizedException("Invalid JWT Token: " + e.getMessage());
}
}
use of org.jose4j.jwt.NumericDate in project cas by apereo.
the class OidcIdTokenGeneratorService method produceIdTokenClaims.
/**
* Produce id token claims jwt claims.
*
* @param request the request
* @param accessTokenId the access token id
* @param timeout the timeout
* @param service the service
* @param profile the user profile
* @param context the context
* @param responseType the response type
* @return the jwt claims
*/
protected JwtClaims produceIdTokenClaims(final HttpServletRequest request, final AccessToken accessTokenId, final long timeout, final OidcRegisteredService service, final UserProfile profile, final J2EContext context, final OAuth20ResponseTypes responseType) {
final Authentication authentication = accessTokenId.getAuthentication();
final Principal principal = authentication.getPrincipal();
final OidcProperties oidc = casProperties.getAuthn().getOidc();
final JwtClaims claims = new JwtClaims();
claims.setJwtId(getOAuthServiceTicket(accessTokenId.getTicketGrantingTicket()).getKey());
claims.setIssuer(oidc.getIssuer());
claims.setAudience(service.getClientId());
final NumericDate expirationDate = NumericDate.now();
expirationDate.addSeconds(timeout);
claims.setExpirationTime(expirationDate);
claims.setIssuedAtToNow();
claims.setNotBeforeMinutesInThePast(oidc.getSkew());
claims.setSubject(principal.getId());
final MultifactorAuthenticationProperties mfa = casProperties.getAuthn().getMfa();
final Map<String, Object> attributes = authentication.getAttributes();
if (attributes.containsKey(mfa.getAuthenticationContextAttribute())) {
final Collection<Object> val = CollectionUtils.toCollection(attributes.get(mfa.getAuthenticationContextAttribute()));
claims.setStringClaim(OidcConstants.ACR, val.iterator().next().toString());
}
if (attributes.containsKey(AuthenticationHandler.SUCCESSFUL_AUTHENTICATION_HANDLERS)) {
final Collection<Object> val = CollectionUtils.toCollection(attributes.get(AuthenticationHandler.SUCCESSFUL_AUTHENTICATION_HANDLERS));
claims.setStringListClaim(OidcConstants.AMR, val.toArray(new String[] {}));
}
claims.setClaim(OAuth20Constants.STATE, attributes.get(OAuth20Constants.STATE));
claims.setClaim(OAuth20Constants.NONCE, attributes.get(OAuth20Constants.NONCE));
claims.setClaim(OidcConstants.CLAIM_AT_HASH, generateAccessTokenHash(accessTokenId, service));
principal.getAttributes().entrySet().stream().filter(entry -> oidc.getClaims().contains(entry.getKey())).forEach(entry -> claims.setClaim(entry.getKey(), entry.getValue()));
if (!claims.hasClaim(OidcConstants.CLAIM_PREFERRED_USERNAME)) {
claims.setClaim(OidcConstants.CLAIM_PREFERRED_USERNAME, profile.getId());
}
return claims;
}
use of org.jose4j.jwt.NumericDate in project kafka by apache.
the class ValidatorAccessTokenValidator method validate.
/**
* Accepts an OAuth JWT access token in base-64 encoded format, validates, and returns an
* OAuthBearerToken.
*
* @param accessToken Non-<code>null</code> JWT access token
* @return {@link OAuthBearerToken}
* @throws ValidateException Thrown on errors performing validation of given token
*/
@SuppressWarnings("unchecked")
public OAuthBearerToken validate(String accessToken) throws ValidateException {
SerializedJwt serializedJwt = new SerializedJwt(accessToken);
JwtContext jwt;
try {
jwt = jwtConsumer.process(serializedJwt.getToken());
} catch (InvalidJwtException e) {
throw new ValidateException(String.format("Could not validate the access token: %s", e.getMessage()), e);
}
JwtClaims claims = jwt.getJwtClaims();
Object scopeRaw = getClaim(() -> claims.getClaimValue(scopeClaimName), scopeClaimName);
Collection<String> scopeRawCollection;
if (scopeRaw instanceof String)
scopeRawCollection = Collections.singletonList((String) scopeRaw);
else if (scopeRaw instanceof Collection)
scopeRawCollection = (Collection<String>) scopeRaw;
else
scopeRawCollection = Collections.emptySet();
NumericDate expirationRaw = getClaim(claims::getExpirationTime, ReservedClaimNames.EXPIRATION_TIME);
String subRaw = getClaim(() -> claims.getStringClaimValue(subClaimName), subClaimName);
NumericDate issuedAtRaw = getClaim(claims::getIssuedAt, ReservedClaimNames.ISSUED_AT);
Set<String> scopes = ClaimValidationUtils.validateScopes(scopeClaimName, scopeRawCollection);
long expiration = ClaimValidationUtils.validateExpiration(ReservedClaimNames.EXPIRATION_TIME, expirationRaw != null ? expirationRaw.getValueInMillis() : null);
String sub = ClaimValidationUtils.validateSubject(subClaimName, subRaw);
Long issuedAt = ClaimValidationUtils.validateIssuedAt(ReservedClaimNames.ISSUED_AT, issuedAtRaw != null ? issuedAtRaw.getValueInMillis() : null);
OAuthBearerToken token = new BasicOAuthBearerToken(accessToken, scopes, expiration, sub, issuedAt);
return token;
}
use of org.jose4j.jwt.NumericDate in project blueocean-plugin by jenkinsci.
the class JwtTokenVerifierImpl method validate.
/**
* @return
* null if the JWT token is not present
* @throws Exception
* if the JWT token is present but invalid
*/
@CheckForNull
private Authentication validate(HttpServletRequest request) {
String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
return null;
}
String token = authHeader.substring("Bearer ".length());
JsonWebStructure jws = parse(token);
if (jws == null) {
return null;
}
try {
String alg = jws.getAlgorithmHeaderValue();
if (alg == null || !alg.equals(RSA_USING_SHA256)) {
logger.error(String.format("Invalid JWT token: unsupported algorithm in header, found %s, expected %s", alg, RSA_USING_SHA256));
throw new ServiceException.UnauthorizedException("Invalid JWT token");
}
String kid = jws.getKeyIdHeaderValue();
if (kid == null) {
logger.error("Invalid JWT token: missing kid");
throw new ServiceException.UnauthorizedException("Invalid JWT token");
}
SigningPublicKey publicKey = JwtSigningKeyProvider.toPublicKey(kid);
if (publicKey == null) {
throw new ServiceException.UnexpectedErrorException("Invalid kid=" + kid);
}
JwtConsumer jwtConsumer = new JwtConsumerBuilder().setRequireExpirationTime().setRequireJwtId().setAllowedClockSkewInSeconds(// allow some leeway in validating time based claims to account for clock skew
30).setRequireSubject().setVerificationKey(// verify the sign with the public key
publicKey.getKey()).build();
try {
JwtContext context = jwtConsumer.process(token);
JwtClaims claims = context.getJwtClaims();
String subject = claims.getSubject();
if (subject.equals("anonymous")) {
// if anonymous, we do not bother checking expiration
return Jenkins.ANONYMOUS2;
} else {
// If not anonymous user, get Authentication object associated with this claim
// We give a change to the authentication store to inspect the claims and if expired it might
// do cleanup of associated Authentication object for example.
JwtAuthenticationStore authenticationStore = getJwtStore(claims.getClaimsMap());
Authentication authentication = authenticationStore.getAuthentication(claims.getClaimsMap());
// Now check if token expired
NumericDate expirationTime = claims.getExpirationTime();
if (expirationTime.isBefore(NumericDate.now())) {
throw new ServiceException.UnauthorizedException("Invalid JWT token: expired");
}
return authentication;
}
} catch (InvalidJwtException e) {
logger.error("Invalid JWT token: " + e.getMessage(), e);
throw new ServiceException.UnauthorizedException("Invalid JWT token");
} catch (MalformedClaimException e) {
logger.error(String.format("Error reading sub header for token %s", jws.getPayload()), e);
throw new ServiceException.UnauthorizedException("Invalid JWT token: malformed claim");
}
} catch (JoseException e) {
logger.error("Error parsing JWT token: " + e.getMessage(), e);
throw new ServiceException.UnauthorizedException("Invalid JWT Token: " + e.getMessage());
}
}
use of org.jose4j.jwt.NumericDate in project box-java-sdk by box.
the class BoxDeveloperEditionAPIConnection method authenticate.
/**
* Authenticates the API connection for Box Developer Edition.
*/
public void authenticate() {
URL url;
try {
url = new URL(this.getTokenURL());
} catch (MalformedURLException e) {
assert false : "An invalid token URL indicates a bug in the SDK.";
throw new RuntimeException("An invalid token URL indicates a bug in the SDK.", e);
}
this.backoffCounter.reset(this.getMaxRetryAttempts() + 1);
NumericDate jwtTime = null;
String jwtAssertion;
String urlParameters;
BoxAPIRequest request;
String json = null;
final BoxLogger logger = BoxLogger.defaultLogger();
while (this.backoffCounter.getAttemptsRemaining() > 0) {
// Reconstruct the JWT assertion, which regenerates the jti claim, with the new "current" time
jwtAssertion = this.constructJWTAssertion(jwtTime);
urlParameters = String.format(JWT_GRANT_TYPE, this.getClientID(), this.getClientSecret(), jwtAssertion);
request = new BoxAPIRequest(this, url, "POST");
request.shouldAuthenticate(false);
request.setBody(urlParameters);
try {
BoxJSONResponse response = (BoxJSONResponse) request.sendWithoutRetry();
json = response.getJSON();
break;
} catch (BoxAPIException apiException) {
long responseReceivedTime = System.currentTimeMillis();
if (!this.backoffCounter.decrement() || (!BoxAPIRequest.isRequestRetryable(apiException) && !BoxAPIRequest.isResponseRetryable(apiException.getResponseCode(), apiException))) {
throw apiException;
}
logger.warn(String.format("Retrying authentication request due to transient error status=%d body=%s", apiException.getResponseCode(), apiException.getResponse()));
try {
List<String> retryAfterHeader = apiException.getHeaders().get("Retry-After");
if (retryAfterHeader == null) {
this.backoffCounter.waitBackoff();
} else {
int retryAfterDelay = Integer.parseInt(retryAfterHeader.get(0)) * 1000;
this.backoffCounter.waitBackoff(retryAfterDelay);
}
} catch (InterruptedException interruptedException) {
Thread.currentThread().interrupt();
throw apiException;
}
long endWaitTime = System.currentTimeMillis();
long secondsSinceResponseReceived = (endWaitTime - responseReceivedTime) / 1000;
try {
// Use the Date advertised by the Box server in the exception
// as the current time to synchronize clocks
jwtTime = this.getDateForJWTConstruction(apiException, secondsSinceResponseReceived);
} catch (Exception e) {
throw apiException;
}
}
}
if (json == null) {
throw new RuntimeException("Unable to read authentication response in SDK.");
}
JsonObject jsonObject = Json.parse(json).asObject();
this.setAccessToken(jsonObject.get("access_token").asString());
this.setLastRefresh(System.currentTimeMillis());
this.setExpires(jsonObject.get("expires_in").asLong() * 1000);
// if token cache is specified, save to cache
if (this.accessTokenCache != null) {
String key = this.getAccessTokenCacheKey();
JsonObject accessTokenCacheInfo = new JsonObject().add("accessToken", this.getAccessToken()).add("lastRefresh", this.getLastRefresh()).add("expires", this.getExpires());
this.accessTokenCache.put(key, accessTokenCacheInfo.toString());
}
}
Aggregations