use of io.helidon.security.Subject in project helidon by oracle.
the class IdcsMtRoleMapperRxProvider method getGrantsFromServer.
/**
* Get grants from IDCS server. The result is cached.
*
* @param idcsTenantId ID of the IDCS tenant
* @param idcsAppName Name of IDCS application
* @param subject subject to get grants for
* @return optional list of grants from server
*/
protected Single<List<? extends Grant>> getGrantsFromServer(String idcsTenantId, String idcsAppName, Subject subject) {
String subjectName = subject.principal().getName();
String subjectType = (String) subject.principal().abacAttribute("sub_type").orElse(defaultIdcsSubjectType());
RoleMapTracing tracing = SecurityTracing.get().roleMapTracing("idcs");
return Single.create(getAppToken(idcsTenantId, tracing)).flatMapSingle(maybeAppToken -> {
if (maybeAppToken.isEmpty()) {
return Single.error(new SecurityException("Application token not available"));
}
return Single.just(maybeAppToken.get());
}).flatMapSingle(appToken -> {
JsonObjectBuilder requestBuilder = JSON.createObjectBuilder().add("mappingAttributeValue", subjectName).add("subjectType", subjectType).add("appName", idcsAppName).add("includeMemberships", true);
JsonArrayBuilder arrayBuilder = JSON.createArrayBuilder();
arrayBuilder.add("urn:ietf:params:scim:schemas:oracle:idcs:Asserter");
requestBuilder.add("schemas", arrayBuilder);
Context parentContext = Contexts.context().orElseGet(Contexts::globalContext);
Context childContext = Context.builder().parent(parentContext).build();
tracing.findParent().ifPresent(childContext::register);
WebClientRequestBuilder post = oidcConfig().generalWebClient().post().context(childContext).uri(multitenantEndpoints.assertEndpoint(idcsTenantId)).headers(it -> {
it.add(Http.Header.AUTHORIZATION, "Bearer " + appToken);
return it;
});
return processRoleRequest(post, requestBuilder.build(), subjectName);
});
}
use of io.helidon.security.Subject in project helidon by oracle.
the class JwtProviderTest method testEcBothWays.
@Test
public void testEcBothWays() {
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("/ec").transport("http").targetUri(URI.create("http://localhost:8080/ec")).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(JwkEC.ALG_ES256)));
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(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"));
}
use of io.helidon.security.Subject 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");
}
}
use of io.helidon.security.Subject in project helidon by oracle.
the class OidcSupportTest method testOutboundFull.
@Test
void testOutboundFull() {
String tokenContent = "huhahihohyhe";
TokenCredential tokenCredential = TokenCredential.builder().token(tokenContent).build();
Subject subject = Subject.builder().addPublicCredential(TokenCredential.class, tokenCredential).build();
ProviderRequest providerRequest = Mockito.mock(ProviderRequest.class);
SecurityContext ctx = Mockito.mock(SecurityContext.class);
when(ctx.user()).thenReturn(Optional.of(subject));
when(providerRequest.securityContext()).thenReturn(ctx);
SecurityEnvironment outboundEnv = SecurityEnvironment.builder().targetUri(URI.create("http://www.example.com:7777")).path("/test").build();
EndpointConfig endpointConfig = EndpointConfig.builder().build();
boolean outboundSupported = provider.isOutboundSupported(providerRequest, outboundEnv, endpointConfig);
assertThat("Outbound should not be supported by default", outboundSupported, is(false));
OutboundSecurityResponse response = provider.outboundSecurity(providerRequest, outboundEnv, endpointConfig).toCompletableFuture().join();
assertThat("Disabled target should have empty headers", response.requestHeaders().size(), is(0));
}
use of io.helidon.security.Subject in project helidon by oracle.
the class GoogleTokenProviderTest method buildOutboundRequest.
private ProviderRequest buildOutboundRequest() {
TokenCredential tc = TokenCredential.create(TOKEN_VALUE, "accounts.google.com", Instant.now(), Instant.now());
Subject subject = Subject.builder().principal(Principal.create("test")).addPublicCredential(tc).build();
SecurityContext context = mock(SecurityContext.class);
when(context.user()).thenReturn(Optional.of(subject));
ProviderRequest request = mock(ProviderRequest.class);
when(request.securityContext()).thenReturn(context);
when(context.executorService()).thenReturn(ForkJoinPool.commonPool());
return request;
}
Aggregations