Search in sources :

Example 11 with Principal

use of io.helidon.security.Principal in project helidon by oracle.

the class HeaderAtnProvider method syncOutbound.

@Override
protected OutboundSecurityResponse syncOutbound(ProviderRequest providerRequest, SecurityEnvironment outboundEnv, EndpointConfig outboundEndpointConfig) {
    Optional<Subject> toPropagate;
    if (subjectType == SubjectType.USER) {
        toPropagate = providerRequest.securityContext().user();
    } else {
        toPropagate = providerRequest.securityContext().service();
    }
    // find the target
    var target = outboundConfig.findTargetCustomObject(outboundEnv, HeaderAtnOutboundConfig.class, HeaderAtnOutboundConfig::create, HeaderAtnOutboundConfig::create);
    // we have no target, let's fall back to original behavior
    if (target.isEmpty()) {
        if (outboundTokenHandler != null) {
            return toPropagate.map(Subject::principal).map(Principal::id).map(id -> respond(outboundEnv, outboundTokenHandler, id)).orElseGet(OutboundSecurityResponse::abstain);
        }
        return OutboundSecurityResponse.abstain();
    }
    // we found a target
    HeaderAtnOutboundConfig outboundConfig = target.get();
    TokenHandler tokenHandler = outboundConfig.tokenHandler().orElse(defaultOutboundTokenHandler);
    return outboundConfig.explicitUser().or(() -> toPropagate.map(Subject::principal).map(Principal::id)).map(id -> respond(outboundEnv, tokenHandler, id)).orElseGet(OutboundSecurityResponse::abstain);
}
Also used : OutboundSecurityResponse(io.helidon.security.OutboundSecurityResponse) ProviderRequest(io.helidon.security.ProviderRequest) Config(io.helidon.config.Config) SubjectType(io.helidon.security.SubjectType) OutboundSecurityProvider(io.helidon.security.spi.OutboundSecurityProvider) SynchronousProvider(io.helidon.security.spi.SynchronousProvider) HashMap(java.util.HashMap) TokenHandler(io.helidon.security.util.TokenHandler) AuthenticationResponse(io.helidon.security.AuthenticationResponse) OutboundConfig(io.helidon.security.providers.common.OutboundConfig) Principal(io.helidon.security.Principal) List(java.util.List) AuthenticationProvider(io.helidon.security.spi.AuthenticationProvider) EndpointConfig(io.helidon.security.EndpointConfig) SecurityEnvironment(io.helidon.security.SecurityEnvironment) OutboundTarget(io.helidon.security.providers.common.OutboundTarget) Map(java.util.Map) Optional(java.util.Optional) Subject(io.helidon.security.Subject) TokenHandler(io.helidon.security.util.TokenHandler) Subject(io.helidon.security.Subject) Principal(io.helidon.security.Principal) OutboundSecurityResponse(io.helidon.security.OutboundSecurityResponse)

Example 12 with Principal

use of io.helidon.security.Principal in project helidon by oracle.

the class OidcProvider method buildPrincipal.

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();
}
Also used : JwtException(io.helidon.security.jwt.JwtException) Principal(io.helidon.security.Principal)

Example 13 with Principal

use of io.helidon.security.Principal in project helidon by oracle.

the class OidcProvider method buildSubject.

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);
    Subject.Builder subjectBuilder = Subject.builder().principal(principal).addPublicCredential(TokenCredential.class, builder.build());
    if (useJwtGroups) {
        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();
}
Also used : Arrays(java.util.Arrays) Security(io.helidon.security.Security) JwtException(io.helidon.security.jwt.JwtException) BiFunction(java.util.function.BiFunction) DeprecatedConfig(io.helidon.config.DeprecatedConfig) MediaType(io.helidon.common.http.MediaType) ScopeValidator(io.helidon.security.abac.scope.ScopeValidator) Matcher(java.util.regex.Matcher) Map(java.util.Map) FormParams(io.helidon.common.http.FormParams) Grant(io.helidon.security.Grant) ConfiguredOption(io.helidon.config.metadata.ConfiguredOption) SecurityLevel(io.helidon.security.SecurityLevel) JwtUtil(io.helidon.security.jwt.JwtUtil) Collection(java.util.Collection) Set(java.util.Set) UUID(java.util.UUID) Logger(java.util.logging.Logger) AuthenticationResponse(io.helidon.security.AuthenticationResponse) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) List(java.util.List) CompletionStage(java.util.concurrent.CompletionStage) Role(io.helidon.security.Role) Annotation(java.lang.annotation.Annotation) Optional(java.util.Optional) Pattern(java.util.regex.Pattern) Errors(io.helidon.common.Errors) OutboundSecurityResponse(io.helidon.security.OutboundSecurityResponse) ProviderRequest(io.helidon.security.ProviderRequest) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) Level(java.util.logging.Level) HashSet(java.util.HashSet) SignedJwt(io.helidon.security.jwt.SignedJwt) OidcCookieHandler(io.helidon.security.providers.oidc.common.OidcCookieHandler) AuthenticationProvider(io.helidon.security.spi.AuthenticationProvider) OidcConfig(io.helidon.security.providers.oidc.common.OidcConfig) BiConsumer(java.util.function.BiConsumer) Single(io.helidon.common.reactive.Single) Subject(io.helidon.security.Subject) TokenCredential(io.helidon.security.providers.common.TokenCredential) LinkedList(java.util.LinkedList) Http(io.helidon.common.http.Http) Config(io.helidon.config.Config) OutboundSecurityProvider(io.helidon.security.spi.OutboundSecurityProvider) Configured(io.helidon.config.metadata.Configured) SecurityProvider(io.helidon.security.spi.SecurityProvider) OidcConfig.postJsonResponse(io.helidon.security.providers.oidc.common.OidcConfig.postJsonResponse) TokenHandler(io.helidon.security.util.TokenHandler) OutboundConfig(io.helidon.security.providers.common.OutboundConfig) Principal(io.helidon.security.Principal) JwkKeys(io.helidon.security.jwt.jwk.JwkKeys) SecurityResponse(io.helidon.security.SecurityResponse) URLEncoder(java.net.URLEncoder) EndpointConfig(io.helidon.security.EndpointConfig) SecurityEnvironment(io.helidon.security.SecurityEnvironment) Jwt(io.helidon.security.jwt.Jwt) OutboundTarget(io.helidon.security.providers.common.OutboundTarget) WebClientRequestBuilder(io.helidon.webclient.WebClientRequestBuilder) List(java.util.List) LinkedList(java.util.LinkedList) TokenCredential(io.helidon.security.providers.common.TokenCredential) Principal(io.helidon.security.Principal) Subject(io.helidon.security.Subject)

Example 14 with Principal

use of io.helidon.security.Principal in project helidon by oracle.

the class JwtProviderTest method testRsaBothWays.

@Test
public void testRsaBothWays() {
    String username = "user1";
    String userId = "user1-id";
    String email = "user1@example.org";
    String familyName = "Novak";
    String givenName = "Standa";
    String fullName = "Standa Novak";
    Locale locale = Locale.CANADA_FRENCH;
    Principal principal = Principal.builder().name(username).id(userId).addAttribute("email", email).addAttribute("email_verified", true).addAttribute("family_name", familyName).addAttribute("given_name", givenName).addAttribute("full_name", fullName).addAttribute("locale", locale).build();
    Subject subject = Subject.create(principal);
    JwtProvider provider = JwtProvider.create(providersConfig.get("jwt"));
    SecurityContext context = Mockito.mock(SecurityContext.class);
    when(context.user()).thenReturn(Optional.of(subject));
    ProviderRequest request = mock(ProviderRequest.class);
    when(request.securityContext()).thenReturn(context);
    SecurityEnvironment outboundEnv = SecurityEnvironment.builder().path("/rsa").transport("http").targetUri(URI.create("http://localhost:8080/rsa")).build();
    EndpointConfig outboundEp = EndpointConfig.create();
    assertThat(provider.isOutboundSupported(request, outboundEnv, outboundEp), is(true));
    OutboundSecurityResponse response = provider.syncOutbound(request, outboundEnv, outboundEp);
    String signedToken = response.requestHeaders().get("Authorization").get(0);
    signedToken = signedToken.substring("bearer ".length());
    // now I want to validate it to prove it was correctly signed
    SignedJwt signedJwt = SignedJwt.parseToken(signedToken);
    signedJwt.verifySignature(verifyKeys).checkValid();
    Jwt jwt = signedJwt.getJwt();
    assertThat(jwt.subject(), is(Optional.of(userId)));
    assertThat(jwt.preferredUsername(), is(Optional.of(username)));
    assertThat(jwt.email(), is(Optional.of(email)));
    assertThat(jwt.emailVerified(), is(Optional.of(true)));
    assertThat(jwt.familyName(), is(Optional.of(familyName)));
    assertThat(jwt.givenName(), is(Optional.of(givenName)));
    assertThat(jwt.fullName(), is(Optional.of(fullName)));
    assertThat(jwt.locale(), is(Optional.of(locale)));
    assertThat(jwt.audience(), is(Optional.of(List.of("audience.application.id"))));
    assertThat(jwt.issuer(), is(Optional.of("jwt.example.com")));
    assertThat(jwt.algorithm(), is(Optional.of(JwkRSA.ALG_RS256)));
    assertThat(jwt.issueTime(), is(not(Optional.empty())));
    jwt.issueTime().ifPresent(instant -> {
        boolean compareResult = Instant.now().minusSeconds(10).compareTo(instant) < 0;
        assertThat("Issue time must not be older than 10 seconds", compareResult, is(true));
        Instant expectedNotBefore = instant.minus(60, ChronoUnit.SECONDS);
        assertThat(jwt.notBefore(), is(Optional.of(expectedNotBefore)));
        Instant expectedExpiry = instant.plus(3600, ChronoUnit.SECONDS);
        assertThat(jwt.expirationTime(), is(Optional.of(expectedExpiry)));
    });
    // now we need to use the same token to invoke authentication
    ProviderRequest atnRequest = mock(ProviderRequest.class);
    SecurityEnvironment se = SecurityEnvironment.builder().header("Authorization", "bearer " + signedToken).build();
    when(atnRequest.env()).thenReturn(se);
    AuthenticationResponse authenticationResponse = provider.syncAuthenticate(atnRequest);
    authenticationResponse.user().map(Subject::principal).ifPresentOrElse(atnPrincipal -> {
        assertThat(atnPrincipal.id(), is(userId));
        assertThat(atnPrincipal.getName(), is(username));
        assertThat(atnPrincipal.abacAttribute("email"), is(Optional.of(email)));
        assertThat(atnPrincipal.abacAttribute("email_verified"), is(Optional.of(true)));
        assertThat(atnPrincipal.abacAttribute("family_name"), is(Optional.of(familyName)));
        assertThat(atnPrincipal.abacAttribute("given_name"), is(Optional.of(givenName)));
        assertThat(atnPrincipal.abacAttribute("full_name"), is(Optional.of(fullName)));
        assertThat(atnPrincipal.abacAttribute("locale"), is(Optional.of(locale)));
    }, () -> fail("User must be present in response"));
}
Also used : Locale(java.util.Locale) SecurityEnvironment(io.helidon.security.SecurityEnvironment) SignedJwt(io.helidon.security.jwt.SignedJwt) Jwt(io.helidon.security.jwt.Jwt) Instant(java.time.Instant) SignedJwt(io.helidon.security.jwt.SignedJwt) AuthenticationResponse(io.helidon.security.AuthenticationResponse) Subject(io.helidon.security.Subject) ProviderRequest(io.helidon.security.ProviderRequest) OutboundSecurityResponse(io.helidon.security.OutboundSecurityResponse) SecurityContext(io.helidon.security.SecurityContext) Principal(io.helidon.security.Principal) EndpointConfig(io.helidon.security.EndpointConfig) Test(org.junit.jupiter.api.Test)

Example 15 with Principal

use of io.helidon.security.Principal in project helidon by oracle.

the class JwtProviderTest method testOctBothWays.

@Test
public void testOctBothWays() {
    String userId = "user1-id";
    Principal tp = Principal.create(userId);
    Subject subject = Subject.create(tp);
    JwtProvider provider = JwtProvider.create(providersConfig.get("jwt"));
    SecurityContext context = Mockito.mock(SecurityContext.class);
    when(context.user()).thenReturn(Optional.of(subject));
    ProviderRequest request = mock(ProviderRequest.class);
    when(request.securityContext()).thenReturn(context);
    SecurityEnvironment outboundEnv = SecurityEnvironment.builder().path("/oct").transport("http").targetUri(URI.create("http://localhost:8080/oct")).build();
    EndpointConfig outboundEp = EndpointConfig.create();
    assertThat(provider.isOutboundSupported(request, outboundEnv, outboundEp), is(true));
    OutboundSecurityResponse response = provider.syncOutbound(request, outboundEnv, outboundEp);
    String signedToken = response.requestHeaders().get("Authorization").get(0);
    signedToken = signedToken.substring("bearer ".length());
    // now I want to validate it to prove it was correctly signed
    SignedJwt signedJwt = SignedJwt.parseToken(signedToken);
    signedJwt.verifySignature(verifyKeys).checkValid();
    Jwt jwt = signedJwt.getJwt();
    assertThat(jwt.subject(), is(Optional.of(userId)));
    assertThat(jwt.preferredUsername(), is(Optional.of(userId)));
    assertThat(jwt.email(), is(Optional.empty()));
    assertThat(jwt.emailVerified(), is(Optional.empty()));
    assertThat(jwt.familyName(), is(Optional.empty()));
    assertThat(jwt.givenName(), is(Optional.empty()));
    // stored as "name" attribute on principal, full name is stored as "name" in JWT
    assertThat(jwt.fullName(), is(Optional.empty()));
    assertThat(jwt.locale(), is(Optional.empty()));
    assertThat(jwt.audience(), is(Optional.of(List.of("audience.application.id"))));
    assertThat(jwt.issuer(), is(Optional.of("jwt.example.com")));
    assertThat(jwt.algorithm(), is(Optional.of(JwkOctet.ALG_HS256)));
    Instant instant = jwt.issueTime().get();
    boolean compareResult = Instant.now().minusSeconds(10).compareTo(instant) < 0;
    assertThat("Issue time must not be older than 10 seconds", compareResult, is(true));
    Instant expectedNotBefore = instant.minus(5, ChronoUnit.SECONDS);
    assertThat(jwt.notBefore(), is(Optional.of(expectedNotBefore)));
    Instant expectedExpiry = instant.plus(60 * 60 * 24, ChronoUnit.SECONDS);
    assertThat(jwt.expirationTime(), is(Optional.of(expectedExpiry)));
    // now we need to use the same token to invoke authentication
    ProviderRequest atnRequest = mock(ProviderRequest.class);
    SecurityEnvironment se = SecurityEnvironment.builder().header("Authorization", "bearer " + signedToken).build();
    when(atnRequest.env()).thenReturn(se);
    AuthenticationResponse authenticationResponse = provider.syncAuthenticate(atnRequest);
    authenticationResponse.user().map(Subject::principal).ifPresentOrElse(atnPrincipal -> {
        assertThat(atnPrincipal.id(), is(userId));
        assertThat(atnPrincipal.getName(), is(userId));
        assertThat(atnPrincipal.abacAttribute("email"), is(Optional.empty()));
        assertThat(atnPrincipal.abacAttribute("email_verified"), is(Optional.empty()));
        assertThat(atnPrincipal.abacAttribute("family_name"), is(Optional.empty()));
        assertThat(atnPrincipal.abacAttribute("given_name"), is(Optional.empty()));
        assertThat(atnPrincipal.abacAttribute("full_name"), is(Optional.empty()));
        assertThat(atnPrincipal.abacAttribute("locale"), is(Optional.empty()));
    }, () -> fail("User must be present in response"));
}
Also used : SecurityEnvironment(io.helidon.security.SecurityEnvironment) SignedJwt(io.helidon.security.jwt.SignedJwt) Jwt(io.helidon.security.jwt.Jwt) Instant(java.time.Instant) SignedJwt(io.helidon.security.jwt.SignedJwt) AuthenticationResponse(io.helidon.security.AuthenticationResponse) Subject(io.helidon.security.Subject) ProviderRequest(io.helidon.security.ProviderRequest) OutboundSecurityResponse(io.helidon.security.OutboundSecurityResponse) SecurityContext(io.helidon.security.SecurityContext) Principal(io.helidon.security.Principal) EndpointConfig(io.helidon.security.EndpointConfig) Test(org.junit.jupiter.api.Test)

Aggregations

Principal (io.helidon.security.Principal)22 Subject (io.helidon.security.Subject)16 ProviderRequest (io.helidon.security.ProviderRequest)13 AuthenticationResponse (io.helidon.security.AuthenticationResponse)12 EndpointConfig (io.helidon.security.EndpointConfig)12 OutboundSecurityResponse (io.helidon.security.OutboundSecurityResponse)12 SecurityEnvironment (io.helidon.security.SecurityEnvironment)12 SignedJwt (io.helidon.security.jwt.SignedJwt)12 SecurityContext (io.helidon.security.SecurityContext)10 Jwt (io.helidon.security.jwt.Jwt)10 Test (org.junit.jupiter.api.Test)10 Instant (java.time.Instant)7 Locale (java.util.Locale)7 JwtException (io.helidon.security.jwt.JwtException)6 Config (io.helidon.config.Config)5 HashMap (java.util.HashMap)4 List (java.util.List)4 Role (io.helidon.security.Role)3 Jwk (io.helidon.security.jwt.jwk.Jwk)3 OutboundConfig (io.helidon.security.providers.common.OutboundConfig)3