Search in sources :

Example 26 with Subject

use of io.helidon.security.Subject 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 27 with Subject

use of io.helidon.security.Subject 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)

Example 28 with Subject

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

the class JwtProviderTest method testInvalidSignatureFail.

@Test
@DisplayName("RSA Invalid Signature: verify-signature = true")
public void testInvalidSignatureFail() {
    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());
    // the token is headers.body.signature
    int lastDot = signedToken.lastIndexOf('.') + 1;
    signedToken = signedToken.substring(0, lastDot) + Base64.getEncoder().encodeToString("invalidSignature".getBytes());
    SignedJwt signedJwt = SignedJwt.parseToken(signedToken);
    assertThat("Should not be valid signature (wrong length)", signedJwt.verifySignature(verifyKeys).isValid(), is(false));
    // 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);
    assertThat(authenticationResponse.status(), is(SecurityResponse.SecurityStatus.FAILURE));
}
Also used : Locale(java.util.Locale) SecurityEnvironment(io.helidon.security.SecurityEnvironment) 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) DisplayName(org.junit.jupiter.api.DisplayName)

Example 29 with Subject

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

the class IdcsRoleMapperRxProviderTest method testCacheUsed.

@Test
void testCacheUsed() {
    ProviderRequest mock = Mockito.mock(ProviderRequest.class);
    String username = "test-user";
    AuthenticationResponse response = provider.map(mock, AuthenticationResponse.builder().user(Subject.builder().principal(Principal.create(username)).build()).build()).toCompletableFuture().join();
    Subject subject = response.user().get();
    List<Role> grants = subject.grants(Role.class);
    assertThat(grants, iterableWithSize(5));
    assertThat(grants, hasItems(Role.create("fixed"), Role.create(username), Role.create("additional-fixed")));
    Role counted = findCounted(grants);
    Role additionalCounted = findAdditionalCounted(grants);
    response = provider.map(mock, AuthenticationResponse.builder().user(Subject.builder().principal(Principal.create(username)).build()).build()).toCompletableFuture().join();
    grants = response.user().get().grants(Role.class);
    assertThat(grants, iterableWithSize(5));
    Role counted2 = findCounted(grants);
    assertThat("Expecting the same role, as it should have been cached", counted2, is(counted));
    Role additionalCounted2 = findAdditionalCounted(grants);
    assertThat("Additional roles should not be cached", additionalCounted2, not(additionalCounted));
}
Also used : Role(io.helidon.security.Role) AuthenticationResponse(io.helidon.security.AuthenticationResponse) Subject(io.helidon.security.Subject) ProviderRequest(io.helidon.security.ProviderRequest) Test(org.junit.jupiter.api.Test)

Example 30 with Subject

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

the class JwtProviderTest method testInvalidSignatureOk.

@Test
@DisplayName("RSA Invalid Signature: verify-signature = false")
public void testInvalidSignatureOk() {
    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-no-verification"));
    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());
    // the token is headers.body.signature
    int lastDot = signedToken.lastIndexOf('.') + 1;
    signedToken = signedToken.substring(0, lastDot) + Base64.getEncoder().encodeToString("invalidSignature".getBytes());
    SignedJwt signedJwt = SignedJwt.parseToken(signedToken);
    assertThat("Should not be valid signature (wrong length)", signedJwt.verifySignature(verifyKeys).isValid(), is(false));
    // 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) 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) DisplayName(org.junit.jupiter.api.DisplayName)

Aggregations

Subject (io.helidon.security.Subject)36 ProviderRequest (io.helidon.security.ProviderRequest)22 SecurityContext (io.helidon.security.SecurityContext)18 SecurityEnvironment (io.helidon.security.SecurityEnvironment)18 AuthenticationResponse (io.helidon.security.AuthenticationResponse)17 Test (org.junit.jupiter.api.Test)17 Principal (io.helidon.security.Principal)16 EndpointConfig (io.helidon.security.EndpointConfig)15 OutboundSecurityResponse (io.helidon.security.OutboundSecurityResponse)15 SignedJwt (io.helidon.security.jwt.SignedJwt)11 Config (io.helidon.config.Config)10 Jwt (io.helidon.security.jwt.Jwt)9 Optional (java.util.Optional)8 Instant (java.time.Instant)7 Locale (java.util.Locale)7 TokenCredential (io.helidon.security.providers.common.TokenCredential)6 LinkedList (java.util.LinkedList)6 List (java.util.List)6 Errors (io.helidon.common.Errors)4 MediaType (io.helidon.common.http.MediaType)4