/** * Validates all default values. * Values validated: * <ul> * <li>{@link #expirationTime() Expiration time} if defined</li> * <li>{@link #issueTime() Issue time} if defined</li> * <li>{@link #notBefore() Not before time} if defined</li> * <li>{@link #issuer()} Issuer} if defined</li> * <li>{@link #audience() Audience} if defined</li> * </ul> * * @param issuer validates that this JWT was issued by this issuer. Setting this to non-null value will make * issuer claim mandatory * @param audience validates that this JWT was issued for this audience. Setting this to non-null value will make * audience claim mandatory * @return errors instance to check for validation result */ public Errors validate(String issuer, String audience) { List<Validator<Jwt>> validators = defaultTimeValidators(); if (null != issuer) { addIssuerValidator(validators, issuer, true); } if (null != audience) { addAudienceValidator(validators, audience, true); } return validate(validators); }
private Subject buildSubject(Jwt jwt, SignedJwt signedJwt) { Principal principal = buildPrincipal(jwt); TokenCredential.Builder builder = TokenCredential.builder(); jwt.issueTime().ifPresent(builder::issueTime); jwt.expirationTime().ifPresent(builder::expTime); jwt.issuer().ifPresent(builder::issuer); builder.token(signedJwt.tokenContent()); builder.addToken(Jwt.class, jwt); builder.addToken(SignedJwt.class, signedJwt); Optional<List<String>> scopes = jwt.scopes(); Subject.Builder subjectBuilder = Subject.builder() .principal(principal) .addPublicCredential(TokenCredential.class, builder.build()); scopes.ifPresent(scopeList -> scopeList.forEach(scope -> subjectBuilder.addGrant(Grant.builder() .name(scope) .type("scope") .build()))); return subjectBuilder.build(); }
Principal buildPrincipal(Jwt jwt) { String subject = jwt.subject() .orElseThrow(() -> new JwtException("JWT does not contain subject claim, cannot create principal.")); String name = jwt.preferredUsername() .orElse(subject); Principal.Builder builder = Principal.builder(); builder.name(name) .id(subject); jwt.payloadClaims() .forEach((key, jsonValue) -> builder.addAttribute(key, JwtUtil.toObject(jsonValue))); jwt.email().ifPresent(value -> builder.addAttribute("email", value)); jwt.emailVerified().ifPresent(value -> builder.addAttribute("email_verified", value)); jwt.locale().ifPresent(value -> builder.addAttribute("locale", value)); jwt.familyName().ifPresent(value -> builder.addAttribute("family_name", value)); jwt.givenName().ifPresent(value -> builder.addAttribute("given_name", value)); jwt.fullName().ifPresent(value -> builder.addAttribute("full_name", value)); return builder.build(); }
private Optional<SignedJwt> getCachedAppToken() { if (null == appToken) { return Optional.empty(); } if (appJwt.validate(Jwt.defaultTimeValidators()).isValid()) { return Optional.of(appToken); } appToken = null; appJwt = null; return Optional.empty(); }
private Object getClaim(Claims claims) { switch (claims) { case raw_token: return signed.tokenContent(); case groups: return jwt.userGroups().map(HashSet::new).orElse(null); case aud: return jwt.audience().map(HashSet::new).orElse(null); case email_verified: return jwt.emailVerified().orElse(null); case phone_number_verified: return jwt.phoneNumberVerified().orElse(null); case upn: return jwt.userPrincipal().orElse(null); default: //do nothing, just continue to processing based on type } String claimName = claims.name(); Optional<JsonValue> json = getJsonValue(claimName); return json.map(value -> convert(claims, value)).orElse(null); }
Errors validationErrors = jwt.validate(oidcConfig.issuer(), oidcConfig.audience());
@Override public void validate(Jwt token, Errors.Collector collector) { token.issueTime().ifPresent(it -> { // must be issued in the past if (latest().isBefore(it)) { collector.fatal(token, "Token was not issued in the past: " + it); } }); } }
@Override public void validate(Jwt token, Errors.Collector collector) { token.expirationTime().ifPresent(it -> { if (earliest().isAfter(it)) { collector.fatal(token, "Token no longer valid, expiration: " + it); } }); } }
private Object getClaim(Claims claims) { switch (claims) { case raw_token: return signed.tokenContent(); case groups: return jwt.userGroups().map(HashSet::new).orElse(null); case aud: return jwt.audience().map(HashSet::new).orElse(null); case email_verified: return jwt.emailVerified().orElse(null); case phone_number_verified: return jwt.phoneNumberVerified().orElse(null); case upn: return jwt.userPrincipal().orElse(null); default: //do nothing, just continue to processing based on type } String claimName = claims.name(); Optional<JsonValue> json = getJsonValue(claimName); return json.map(value -> convert(claims, value)).orElse(null); }
AuthenticationResponse authenticate(ProviderRequest providerRequest, LoginConfig loginConfig) { return atnTokenHandler.extractToken(providerRequest.env().headers()) .map(token -> { SignedJwt signedJwt = SignedJwt.parseToken(token); Errors errors = signedJwt.verifySignature(verifyKeys, defaultJwk); if (errors.isValid()) { Jwt jwt = signedJwt.getJwt(); // verify the audience is correct Errors validate = jwt.validate(expectedIssuer, expectedAudience); if (validate.isValid()) { return AuthenticationResponse.success(buildSubject(jwt, signedJwt)); } else { return AuthenticationResponse.failed("Audience is invalid or missing: " + expectedAudience); } } else { return AuthenticationResponse.failed(errors.toString()); } }).orElseGet(() -> { if (optional) { return AuthenticationResponse.abstain(); } else { return AuthenticationResponse.failed("Header not available or in a wrong format"); } }); }
@Override public void validate(Jwt token, Errors.Collector collector) { token.issueTime().ifPresent(it -> { // must be issued in the past if (latest().isBefore(it)) { collector.fatal(token, "Token was not issued in the past: " + it); } }); } }
@Override public void validate(Jwt token, Errors.Collector collector) { token.expirationTime().ifPresent(it -> { if (earliest().isAfter(it)) { collector.fatal(token, "Token no longer valid, expiration: " + it); } }); } }
private Principal buildPrincipal(Jwt jwt) { String subject = jwt.subject() .orElseThrow(() -> new JwtException("JWT does not contain subject claim, cannot create principal.")); String name = jwt.preferredUsername() .orElse(subject); Principal.Builder builder = Principal.builder(); builder.name(name) .id(subject); jwt.payloadClaims() .forEach((key, jsonValue) -> builder.addAttribute(key, JwtUtil.toObject(jsonValue))); jwt.email().ifPresent(value -> builder.addAttribute("email", value)); jwt.emailVerified().ifPresent(value -> builder.addAttribute("email_verified", value)); jwt.locale().ifPresent(value -> builder.addAttribute("locale", value)); jwt.familyName().ifPresent(value -> builder.addAttribute("family_name", value)); jwt.givenName().ifPresent(value -> builder.addAttribute("given_name", value)); jwt.fullName().ifPresent(value -> builder.addAttribute("full_name", value)); return builder.build(); } }
Subject buildSubject(Jwt jwt, SignedJwt signedJwt) { JsonWebTokenImpl principal = buildPrincipal(jwt, signedJwt); TokenCredential.Builder builder = TokenCredential.builder(); jwt.issueTime().ifPresent(builder::issueTime); jwt.expirationTime().ifPresent(builder::expTime); jwt.issuer().ifPresent(builder::issuer); builder.token(signedJwt.tokenContent()); builder.addToken(JsonWebToken.class, principal); builder.addToken(Jwt.class, jwt); builder.addToken(SignedJwt.class, signedJwt); Subject.Builder subjectBuilder = Subject.builder() .principal(principal) .addPublicCredential(TokenCredential.class, builder.build()); Optional<List<String>> userGroups = jwt.userGroups(); userGroups.ifPresent(groups -> groups.forEach(group -> subjectBuilder.addGrant(Role.create(group)))); Optional<List<String>> scopes = jwt.scopes(); scopes.ifPresent(scopeList -> scopeList.forEach(scope -> subjectBuilder.addGrant(Grant.builder() .name(scope) .type("scope") .build()))); return subjectBuilder.build(); }
/** * Validates all default values. * Values validated: * <ul> * <li>{@link #expirationTime() Expiration time} if defined</li> * <li>{@link #issueTime() Issue time} if defined</li> * <li>{@link #notBefore() Not before time} if defined</li> * <li>{@link #issuer()} Issuer} if defined</li> * <li>{@link #audience() Audience} if defined</li> * </ul> * * @param issuer validates that this JWT was issued by this issuer. Setting this to non-null value will make * issuer claim mandatory * @param audience validates that this JWT was issued for this audience. Setting this to non-null value will make * audience claim mandatory * @return errors instance to check for validation result */ public Errors validate(String issuer, String audience) { List<Validator<Jwt>> validators = defaultTimeValidators(); if (null != issuer) { addIssuerValidator(validators, issuer, true); } if (null != audience) { addAudienceValidator(validators, audience, true); } return validate(validators); }
@Override protected AuthenticationResponse syncAuthenticate(ProviderRequest providerRequest) { if (!authenticate) { return AuthenticationResponse.abstain(); } return atnTokenHandler.extractToken(providerRequest.env().headers()) .map(token -> { SignedJwt signedJwt = SignedJwt.parseToken(token); Errors errors = signedJwt.verifySignature(verifyKeys); if (errors.isValid()) { Jwt jwt = signedJwt.getJwt(); // verify the audience is correct Errors validate = jwt.validate(null, expectedAudience); if (validate.isValid()) { return AuthenticationResponse.success(buildSubject(jwt, signedJwt)); } else { return AuthenticationResponse.failed("Audience is invalid or missing: " + expectedAudience); } } else { return AuthenticationResponse.failed(errors.toString()); } }).orElseGet(() -> { if (optional) { return AuthenticationResponse.abstain(); } else { return AuthenticationResponse.failed("Header not available or in a wrong format"); } }); }
private JsonWebTokenImpl(SignedJwt signed) { this.jwt = signed.getJwt(); this.signed = signed; BasicAttributes container = BasicAttributes.create(); jwt.payloadClaims() .forEach((key, jsonValue) -> container.put(key, JwtUtil.toObject(jsonValue))); jwt.email().ifPresent(value -> container.put("email", value)); jwt.emailVerified().ifPresent(value -> container.put("email_verified", value)); jwt.locale().ifPresent(value -> container.put("locale", value)); jwt.familyName().ifPresent(value -> container.put("family_name", value)); jwt.givenName().ifPresent(value -> container.put("given_name", value)); jwt.fullName().ifPresent(value -> container.put("full_name", value)); this.properties = container; String subject = jwt.subject() .orElseThrow(() -> new JwtException("JWT does not contain subject claim, cannot create principal.")); this.name = OptionalHelper.from(jwt.userPrincipal()) .or(jwt::preferredUsername).asOptional() .orElse(subject); this.id = subject; }
Subject buildSubject(Jwt jwt, SignedJwt signedJwt) { Principal principal = buildPrincipal(jwt); TokenCredential.Builder builder = TokenCredential.builder(); jwt.issueTime().ifPresent(builder::issueTime); jwt.expirationTime().ifPresent(builder::expTime); jwt.issuer().ifPresent(builder::issuer); builder.token(signedJwt.tokenContent()); builder.addToken(Jwt.class, jwt); builder.addToken(SignedJwt.class, signedJwt); Optional<List<String>> scopes = jwt.scopes(); Subject.Builder subjectBuilder = Subject.builder() .principal(principal) .addPublicCredential(TokenCredential.class, builder.build()); scopes.ifPresent(scopeList -> { scopeList.forEach(scope -> subjectBuilder.addGrant(Grant.builder() .name(scope) .type("scope") .build())); }); return subjectBuilder.build(); }
AuthenticationResponse authenticate(ProviderRequest providerRequest, LoginConfig loginConfig) { return atnTokenHandler.extractToken(providerRequest.env().headers()) .map(token -> { SignedJwt signedJwt = SignedJwt.parseToken(token); Errors errors = signedJwt.verifySignature(verifyKeys, defaultJwk); if (errors.isValid()) { Jwt jwt = signedJwt.getJwt(); // verify the audience is correct Errors validate = jwt.validate(expectedIssuer, expectedAudience); if (validate.isValid()) { return AuthenticationResponse.success(buildSubject(jwt, signedJwt)); } else { return AuthenticationResponse.failed("Audience is invalid or missing: " + expectedAudience); } } else { return AuthenticationResponse.failed(errors.toString()); } }).orElseGet(() -> { if (optional) { return AuthenticationResponse.abstain(); } else { return AuthenticationResponse.failed("Header not available or in a wrong format"); } }); }
Principal buildPrincipal(Jwt jwt) { String subject = jwt.subject() .orElseThrow(() -> new JwtException("JWT does not contain subject claim, cannot create principal.")); String name = jwt.preferredUsername() .orElse(subject); Principal.Builder builder = Principal.builder(); builder.name(name) .id(subject); jwt.payloadClaims() .forEach((key, jsonValue) -> builder.addAttribute(key, JwtUtil.toObject(jsonValue))); jwt.email().ifPresent(value -> builder.addAttribute("email", value)); jwt.emailVerified().ifPresent(value -> builder.addAttribute("email_verified", value)); jwt.locale().ifPresent(value -> builder.addAttribute("locale", value)); jwt.familyName().ifPresent(value -> builder.addAttribute("family_name", value)); jwt.givenName().ifPresent(value -> builder.addAttribute("given_name", value)); jwt.fullName().ifPresent(value -> builder.addAttribute("full_name", value)); return builder.build(); }