collector.hint(this, "There are no required scopes for current request."); return; collector.fatal(this, "Access requires scopes: " + config.requiredScopes() + ", yet the user is in " + "neither of them: " + userScopes); return; collector.fatal(this, "User is not in all required scopes: " + config.requiredScopes() + ", user's " + "scopes: " + userScopes); List<String> requiredScopes = config.requiredScopes(); if (!requiredScopes.isEmpty()) { collector.fatal(this, "User not logged int. Required scopes: " + requiredScopes);
collector.warn("Neither alg nor kid are specified in JWT, assuming none algorithm"); jwk = (defaultJwk == null) ? Jwk.NONE_JWK : defaultJwk; alg = jwk.algorithm(); if (null == jwk) { if (null == defaultJwk) { collector.fatal(keys, "Key for key id: " + kid + " not found"); } else { jwk = defaultJwk; jwk = defaultJwk; if (null == jwk) { collector.fatal("Algorithm is " + alg + ", yet no kid is defined in JWT header, cannot validate"); collector.fatal(keys, "Key for key id: " + kid + " not found"); return collector.collect(); collector.fatal(jwk, "Signature of JWT token is not valid, based on alg: " + alg + ", kid: " + kid); collector.fatal(jwk, "Algorithm of JWK (" + jwk .algorithm() + ") does not match algorithm of this JWT (" + alg + ") for kid: " + kid); return collector.collect();
Errors errors = collector.collect();
collector.hint(this, "There are no required scopes for current request."); return; collector.fatal(this, "Access requires scopes: " + config.requiredScopes() + ", yet the user is in " + "neither of them: " + userScopes); return; collector.fatal(this, "User is not in all required scopes: " + config.requiredScopes() + ", user's " + "scopes: " + userScopes); List<String> requiredScopes = config.requiredScopes(); if (!requiredScopes.isEmpty()) { collector.fatal(this, "User not logged int. Required scopes: " + requiredScopes);
@Override public void executePolicy(String policyStatement, Errors.Collector collector, ProviderRequest request) { StandardELContext context = new StandardELContext(ef); context.addELResolver(ATTRIBUTE_RESOLVER); FunctionMapper functions = context.getFunctionMapper(); VariableMapper variables = context.getVariableMapper(); customMethods.forEach(customFunction -> functions.mapFunction(customFunction.prefix, customFunction.localName, customFunction.method)); Subject userSubject = request.subject().orElse(SecurityContext.ANONYMOUS); variable(variables, "user", userSubject, Subject.class); variable(variables, "subject", userSubject, Subject.class); variable(variables, "service", request.service().orElse(SecurityContext.ANONYMOUS), Subject.class); variable(variables, "env", request.env(), SecurityEnvironment.class); variable(variables, "object", request.getObject().orElse(null), Object.class); variable(variables, "request", request, ProviderRequest.class); try { ValueExpression expression = ef.createValueExpression(context, policyStatement, boolean.class); boolean value = (boolean) expression.getValue(context); if (!value) { collector.fatal(this, "Policy statement \"" + policyStatement + "\" evaluated to false"); } } catch (Exception e) { collector.fatal(this, "Policy statement \"" + policyStatement + "\" evaluated to an exception " + e.getClass() .getName() + " with message: " + e.getMessage()); LOGGER.log(Level.FINEST, e, () -> "Statement " + policyStatement + " evaluation failed"); } }
@Override public void executePolicy(String policyStatement, Errors.Collector collector, ProviderRequest request) { StandardELContext context = new StandardELContext(ef); context.addELResolver(ATTRIBUTE_RESOLVER); FunctionMapper functions = context.getFunctionMapper(); VariableMapper variables = context.getVariableMapper(); customMethods.forEach(customFunction -> functions.mapFunction(customFunction.prefix, customFunction.localName, customFunction.method)); Subject userSubject = request.getSubject().orElse(SecurityContext.ANONYMOUS); variable(variables, "user", userSubject, Subject.class); variable(variables, "subject", userSubject, Subject.class); variable(variables, "service", request.getService().orElse(SecurityContext.ANONYMOUS), Subject.class); variable(variables, "env", request.getEnv(), SecurityEnvironment.class); variable(variables, "object", request.getObject().orElse(null), Object.class); variable(variables, "request", request, ProviderRequest.class); try { ValueExpression expression = ef.createValueExpression(context, policyStatement, boolean.class); boolean value = (boolean) expression.getValue(context); if (!value) { collector.fatal(this, "Policy statement \"" + policyStatement + "\" evaluated to false"); } } catch (Exception e) { collector.fatal(this, "Policy statement \"" + policyStatement + "\" evaluated to an exception " + e.getClass() .getName() + " with message: " + e.getMessage()); LOGGER.log(Level.FINEST, e, () -> "Statement " + policyStatement + " evaluation failed"); } }
/** * Add validator of audience to the collection of validators. * * @param validators collection of validators * @param audience audience expected to be in the token * @param mandatory whether the audience field is mandatory in the token */ public static void addAudienceValidator(Collection<Validator<Jwt>> validators, String audience, boolean mandatory) { validators.add((jwt, collector) -> { Optional<List<String>> jwtAudiences = jwt.audience(); if (jwtAudiences.isPresent()) { if (jwtAudiences.get().contains(audience)) { return; } collector.fatal(jwt, "Audience must contain " + audience + ", yet it is: " + jwtAudiences); } else { if (mandatory) { collector.fatal(jwt, "Audience is expected to be: " + audience + ", yet no audience in JWT"); } } }); }
@Override public void validate(PolicyConfig config, Errors.Collector collector, ProviderRequest request) { List<String> unvalidatedStatements = new LinkedList<>(); boolean isValidated; for (String statement : config.getPolicyStatements()) { isValidated = false; for (PolicyExecutor executor : executors) { if (executor.supports(statement, request)) { executor.executePolicy(statement, collector, request); isValidated = true; break; } } if (!isValidated) { unvalidatedStatements.add(statement); } } if (!unvalidatedStatements.isEmpty()) { collector.fatal("Some policy statements were not evaluated, cannot continue: " + unvalidatedStatements); } }
private void validate(Set<String> rolesAllowed, Errors.Collector collector, Optional<Subject> subject, SubjectType type) { if (rolesAllowed.isEmpty()) { // no required roles return; } Set<String> roleGrants = subject .map(sub -> sub.grants(Role.class)) .orElse(CollectionsHelper.listOf()) .stream() .map(Role::getName) .collect(Collectors.toSet()); boolean notFound = true; for (String role : rolesAllowed) { if (roleGrants.contains(role)) { notFound = false; break; } } if (notFound) { collector.fatal(this, type + " is not in required roles: " + rolesAllowed + ", only in: " + roleGrants); } }
/** * Validate this JWT against provided validators. * * @param validators Validators to validate with. Obtain them through (e.g.) {@link #defaultTimeValidators()} * , {@link #addAudienceValidator(Collection, String, boolean)} * , {@link #addIssuerValidator(Collection, String, boolean)} * @return errors instance to check if valid and access error messages */ public Errors validate(List<Validator<Jwt>> validators) { Errors.Collector collector = Errors.collector(); validators.forEach(it -> it.validate(this, collector)); return collector.collect(); }
@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); } }); } }
private static byte[] decodeBytes(String base64, Errors.Collector collector, String description) { try { return URL_DECODER.decode(base64); } catch (Exception e) { collector.fatal(base64, description + " is not a base64 encoded string."); return null; } }
@Override public void validate(Jwt token, Errors.Collector collector) { token.notBefore().ifPresent(it -> { if (latest().isBefore(it)) { collector.fatal(token, "Token not yet valid, not before: " + it); } }); } }
<T> Optional<T> validate(String name, Optional<T> optional, Errors.Collector collector) { if (mandatory && !optional.isPresent()) { collector.fatal("Field " + name + " is mandatory, yet not defined in JWT"); } return optional; } }