Search in sources :

Example 6 with Errors

use of io.helidon.common.Errors in project helidon by oracle.

the class AbacProvider method syncAuthorize.

@Override
protected AuthorizationResponse syncAuthorize(ProviderRequest providerRequest) {
    // let's find attributes to be validated
    Errors.Collector collector = Errors.collector();
    List<RuntimeAttribute> attributes = new ArrayList<>();
    EndpointConfig epConfig = providerRequest.endpointConfig();
    // list all "Attribute" annotations and make sure we support them
    validateAnnotations(epConfig, collector);
    // list all children of abac config and make sure one of the AbacValidators supports them
    validateConfig(epConfig, collector);
    // list all custom objects and check those that implement AttributeConfig and ...
    validateCustom(epConfig, collector);
    Optional<Config> abacConfig = epConfig.config(CONFIG_KEY);
    for (var validator : validators) {
        // order of preference - explicit class, configuration, annotation
        Class<? extends AbacValidatorConfig> configClass = validator.configClass();
        String configKey = validator.configKey();
        Collection<Class<? extends Annotation>> annotations = validator.supportedAnnotations();
        Optional<? extends AbacValidatorConfig> customObject = epConfig.instance(configClass);
        if (customObject.isPresent()) {
            attributes.add(new RuntimeAttribute(validator, customObject.get()));
        } else {
            // only configure this validator if its config key exists
            // or it has a supported annotation
            abacConfig.flatMap(it -> it.get(configKey).asNode().asOptional()).ifPresentOrElse(attribConfig -> {
                attributes.add(new RuntimeAttribute(validator, validator.fromConfig(attribConfig)));
            }, () -> {
                List<Annotation> annotationConfig = new ArrayList<>();
                for (SecurityLevel securityLevel : epConfig.securityLevels()) {
                    for (Class<? extends Annotation> annotation : annotations) {
                        List<? extends Annotation> list = securityLevel.combineAnnotations(annotation, EndpointConfig.AnnotationScope.values());
                        annotationConfig.addAll(list);
                    }
                }
                if (!annotationConfig.isEmpty()) {
                    attributes.add(new RuntimeAttribute(validator, validator.fromAnnotations(epConfig)));
                }
            });
        }
    }
    for (RuntimeAttribute attribute : attributes) {
        validate(attribute.getValidator(), attribute.getConfig(), collector, providerRequest);
    }
    Errors errors = collector.collect();
    if (errors.isValid()) {
        return AuthorizationResponse.permit();
    }
    return AuthorizationResponse.builder().status(SecurityResponse.SecurityStatus.FAILURE).description(errors.toString()).build();
}
Also used : ProviderRequest(io.helidon.security.ProviderRequest) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Map(java.util.Map) AuthorizationProvider(io.helidon.security.spi.AuthorizationProvider) LinkedList(java.util.LinkedList) ConfiguredOption(io.helidon.config.metadata.ConfiguredOption) SecurityLevel(io.helidon.security.SecurityLevel) RolesAllowed(jakarta.annotation.security.RolesAllowed) AuthorizationResponse(io.helidon.security.AuthorizationResponse) DenyAll(jakarta.annotation.security.DenyAll) Config(io.helidon.config.Config) Collection(java.util.Collection) Configured(io.helidon.config.metadata.Configured) SecurityProvider(io.helidon.security.spi.SecurityProvider) SynchronousProvider(io.helidon.security.spi.SynchronousProvider) Set(java.util.Set) ServiceLoader(java.util.ServiceLoader) PermitAll(jakarta.annotation.security.PermitAll) HelidonServiceLoader(io.helidon.common.serviceloader.HelidonServiceLoader) Collectors(java.util.stream.Collectors) SecurityResponse(io.helidon.security.SecurityResponse) AbacValidatorService(io.helidon.security.providers.abac.spi.AbacValidatorService) List(java.util.List) EndpointConfig(io.helidon.security.EndpointConfig) Annotation(java.lang.annotation.Annotation) Optional(java.util.Optional) Errors(io.helidon.common.Errors) Collections(java.util.Collections) AbacValidator(io.helidon.security.providers.abac.spi.AbacValidator) Config(io.helidon.config.Config) EndpointConfig(io.helidon.security.EndpointConfig) ArrayList(java.util.ArrayList) Annotation(java.lang.annotation.Annotation) Errors(io.helidon.common.Errors) SecurityLevel(io.helidon.security.SecurityLevel) EndpointConfig(io.helidon.security.EndpointConfig)

Example 7 with Errors

use of io.helidon.common.Errors in project helidon by oracle.

the class SignedJwt method verifySignature.

/**
 * Verify signature against the provided keys (the kid of thisPrincipal
 * JWT should be present in the {@link JwkKeys} provided).
 *
 * @param keys       JwkKeys to obtain a key to verify signature
 * @param defaultJwk Default value of JWK
 * @return Errors with collected messages, see {@link Errors#isValid()} and {@link Errors#checkValid()}
 */
public Errors verifySignature(JwkKeys keys, Jwk defaultJwk) {
    Errors.Collector collector = Errors.collector();
    String alg = headers.algorithm().orElse(null);
    String kid = headers.keyId().orElse(null);
    Jwk jwk = null;
    boolean jwtWithoutKidAndNoneAlg = false;
    // TODO support multiple JWK under same kid if different alg (see if spec allows this)
    if (null == alg) {
        if (null == kid) {
            if (defaultJwk == null) {
                jwtWithoutKidAndNoneAlg = true;
                jwk = Jwk.NONE_JWK;
            } else {
                jwk = defaultJwk;
            }
            alg = jwk.algorithm();
        } else {
            // null alg, non-null kid - will use alg of jwk
            jwk = keys.forKeyId(kid).orElse(null);
            if (null == jwk) {
                if (null == defaultJwk) {
                    collector.fatal(keys, "Key for key id: " + kid + " not found");
                } else {
                    jwk = defaultJwk;
                }
            }
            if (null != jwk) {
                alg = jwk.algorithm();
            }
        }
    } else {
        // alg not null
        if (null == kid) {
            if (Jwk.ALG_NONE.equals(alg)) {
                if (null != defaultJwk) {
                    if (defaultJwk.algorithm().equals(alg)) {
                    // yes, we expect none algorithm
                    } else {
                        collector.fatal("Algorithm is " + alg + ", default jwk requires " + defaultJwk.algorithm());
                    }
                } else {
                    jwk = Jwk.NONE_JWK;
                    jwtWithoutKidAndNoneAlg = true;
                }
            } else {
                jwk = defaultJwk;
                if (null == jwk) {
                    collector.fatal("Algorithm is " + alg + ", yet no kid is defined in JWT header, cannot validate");
                }
            }
        } else {
            // both not null
            jwk = keys.forKeyId(kid).orElse(null);
            if (null == jwk) {
                if ((null != defaultJwk) && alg.equals(defaultJwk.algorithm())) {
                    jwk = defaultJwk;
                }
                if (null == jwk) {
                    collector.fatal(keys, "Key for key id: " + kid + " not found");
                }
            }
        }
    }
    if (null == jwk) {
        return collector.collect();
    }
    if (jwtWithoutKidAndNoneAlg) {
        collector.fatal(jwk, "None algorithm not allowed, unless specified as the default JWK");
    }
    // now if jwk algorithm is none, alg may be
    if (jwk.algorithm().equals(alg)) {
        try {
            if (!jwk.verifySignature(signedBytes, signature)) {
                collector.fatal(jwk, "Signature of JWT token is not valid, based on alg: " + alg + ", kid: " + kid);
            }
        } catch (Exception e) {
            collector.fatal(jwk, "Failed to verify signature due to an exception: " + e.getClass().getName() + ": " + e.getMessage());
        }
    } else {
        collector.fatal(jwk, "Algorithm of JWK (" + jwk.algorithm() + ") does not match algorithm of this JWT (" + alg + ") for kid: " + kid);
    }
    return collector.collect();
}
Also used : Errors(io.helidon.common.Errors) Jwk(io.helidon.security.jwt.jwk.Jwk)

Example 8 with Errors

use of io.helidon.common.Errors in project helidon by oracle.

the class OidcProvider method processValidationResult.

private AuthenticationResponse processValidationResult(ProviderRequest providerRequest, SignedJwt signedJwt, Errors.Collector collector) {
    Jwt jwt = signedJwt.getJwt();
    Errors errors = collector.collect();
    Errors validationErrors = jwt.validate(oidcConfig.issuer(), oidcConfig.audience());
    if (errors.isValid() && validationErrors.isValid()) {
        errors.log(LOGGER);
        Subject subject = buildSubject(jwt, signedJwt);
        Set<String> scopes = subject.grantsByType("scope").stream().map(Grant::getName).collect(Collectors.toSet());
        // make sure we have the correct scopes
        Set<String> expectedScopes = expectedScopes(providerRequest);
        List<String> missingScopes = new LinkedList<>();
        for (String expectedScope : expectedScopes) {
            if (!scopes.contains(expectedScope)) {
                missingScopes.add(expectedScope);
            }
        }
        if (missingScopes.isEmpty()) {
            return AuthenticationResponse.success(subject);
        } else {
            return errorResponse(providerRequest, Http.Status.FORBIDDEN_403, "insufficient_scope", "Scopes " + missingScopes + " are missing");
        }
    } else {
        if (LOGGER.isLoggable(Level.FINEST)) {
            // only log errors when details requested
            errors.log(LOGGER);
            validationErrors.log(LOGGER);
        }
        return errorResponse(providerRequest, Http.Status.UNAUTHORIZED_401, "invalid_token", "Token not valid");
    }
}
Also used : Errors(io.helidon.common.Errors) SignedJwt(io.helidon.security.jwt.SignedJwt) Jwt(io.helidon.security.jwt.Jwt) Subject(io.helidon.security.Subject) LinkedList(java.util.LinkedList)

Example 9 with Errors

use of io.helidon.common.Errors in project helidon by oracle.

the class SignedJwtTest method testSingatureNoAlgNoKid.

@Test
public void testSingatureNoAlgNoKid() {
    Jwt jwt = Jwt.builder().build();
    Jwk defaultJwk = Jwk.NONE_JWK;
    SignedJwt signed = SignedJwt.sign(jwt, customKeys);
    assertThat(signed, notNullValue());
    assertThat(signed.getSignature(), notNullValue());
    assertThat(signed.getSignature(), is(new byte[0]));
    Errors errors = signed.verifySignature(customKeys, defaultJwk);
    assertThat(errors, notNullValue());
    errors.log(LOGGER);
    errors.checkValid();
}
Also used : Errors(io.helidon.common.Errors) Jwk(io.helidon.security.jwt.jwk.Jwk) Test(org.junit.jupiter.api.Test)

Example 10 with Errors

use of io.helidon.common.Errors in project helidon by oracle.

the class SignedJwtTest method testVerify.

@Test
public void testVerify() {
    SignedJwt signedJwt = SignedJwt.parseToken(AUTH_0_TOKEN);
    Errors errors = signedJwt.verifySignature(auth0Keys);
    assertThat(errors, notNullValue());
    errors.checkValid();
}
Also used : Errors(io.helidon.common.Errors) Test(org.junit.jupiter.api.Test)

Aggregations

Errors (io.helidon.common.Errors)12 Test (org.junit.jupiter.api.Test)6 Jwk (io.helidon.security.jwt.jwk.Jwk)4 Jwt (io.helidon.security.jwt.Jwt)2 SignedJwt (io.helidon.security.jwt.SignedJwt)2 LinkedList (java.util.LinkedList)2 HelidonServiceLoader (io.helidon.common.serviceloader.HelidonServiceLoader)1 Config (io.helidon.config.Config)1 Configured (io.helidon.config.metadata.Configured)1 ConfiguredOption (io.helidon.config.metadata.ConfiguredOption)1 AuthorizationResponse (io.helidon.security.AuthorizationResponse)1 EndpointConfig (io.helidon.security.EndpointConfig)1 ProviderRequest (io.helidon.security.ProviderRequest)1 SecurityLevel (io.helidon.security.SecurityLevel)1 SecurityResponse (io.helidon.security.SecurityResponse)1 Subject (io.helidon.security.Subject)1 JwtException (io.helidon.security.jwt.JwtException)1 JwkEC (io.helidon.security.jwt.jwk.JwkEC)1 JwkRSA (io.helidon.security.jwt.jwk.JwkRSA)1 AbacValidator (io.helidon.security.providers.abac.spi.AbacValidator)1