private Subject buildSubject(Subject originalSubject, List<? extends Grant> grants) { Subject.Builder builder = Subject.builder(); builder.update(originalSubject); grants.forEach(builder::addGrant); return builder.build(); }
/** * Check if subject has the specified scope. * * @param subject subject of a user * @param scope scope the subject should have * @return true if the subject has all the specified scopes */ public static boolean inScope(Subject subject, String scope) { List<String> grants = subject.grantsByType("scope").stream().map(Grant::getName).collect(Collectors.toList()); return grants.contains(scope); }
private void atnSpanFinish(Span atnSpan, AuthenticationResponse response) { response.user() .ifPresent(subject -> atnSpan .log("security.user: " + subject.principal().getName())); response.service() .ifPresent(subject -> atnSpan.log("security.service: " + subject.principal().getName())); atnSpan.log("status: " + response.status()); atnSpan.finish(); }
@Override public boolean isOutboundSupported(ProviderRequest providerRequest, SecurityEnvironment outboundEnv, EndpointConfig outboundConfig) { return providerRequest.securityContext() .user() .flatMap(subject -> subject.publicCredential(TokenCredential.class)) .flatMap(token -> token.getIssuer() .map(issuer -> issuer.endsWith(".google.com"))) .orElse(false); }
/** * Get a set of roles the subject has, based on {@link Role Role}. * This is the set of roles as assumed by authentication provider. Authorization providers may use a different set of * roles (and context used authorization provider to check {@link SecurityContext#isUserInRole(String)}). * * @param subject Subject of a user/service * @return set of roles the user/service is in */ public static Set<String> getRoles(Subject subject) { return subject.grants(Role.class) .stream() .map(Role::getName) .collect(Collectors.toSet()); }
.addParam(plain("targetUri", req.uri())); securityContext.service().ifPresent(svc -> auditEvent.addParam(plain("service", svc.toString())));
private CompletionStage<AuthenticationResponse> enhance(Subject subject, AuthenticationResponse previousResponse) { String username = subject.principal().getName(); List<? extends Grant> grants = roleCache.computeValue(username, () -> getGrantsFromServer(username)) .orElse(CollectionsHelper.listOf()); AuthenticationResponse.Builder builder = AuthenticationResponse.builder(); builder.user(buildSubject(subject, grants)); previousResponse.service().ifPresent(builder::service); previousResponse.description().ifPresent(builder::description); builder.requestHeaders(previousResponse.requestHeaders()); AuthenticationResponse response = builder.build(); return CompletableFuture.completedFuture(response); }
@Override protected OutboundSecurityResponse syncOutbound(ProviderRequest providerRequest, SecurityEnvironment outboundEnv, EndpointConfig outboundEndpointConfig) { return providerRequest.securityContext() .user() .flatMap(subject -> subject.publicCredential(TokenCredential.class)) .map(token -> outboundSecurity(providerRequest, outboundEnv, outboundEndpointConfig, token)) .orElse(OutboundSecurityResponse.abstain()); }
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); } }
.addParam(plain("targetUri", req.uri())); securityContext.getService().ifPresent(svc -> auditEvent.addParam(plain("service", svc.toString())));
/** * Create a new subject for a principal. * If you want to configure additional details ({@link Grant Grants}, public and/or private credentials, additional * {@link Principal Principals}), please use fluent API {@link #builder()}. * * @param principal principal this subject represents * @return a new subject instance with the single principal */ public static Subject create(Principal principal) { return builder().principal(principal).build(); }
protected void authenticate(SecurityFilter.FilterContext context, Span securitySpan, SecurityContext securityContext) { Span atnSpan = startNewSpan(securitySpan.context(), "security:atn"); try { SecurityDefinition methodSecurity = context.getMethodSecurity(); if (methodSecurity.requiresAuthentication()) { //authenticate request SecurityClientBuilder<AuthenticationResponse> clientBuilder = securityContext .atnClientBuilder() .optional(methodSecurity.authenticationOptional()) .requestMessage(toRequestMessage(context)) .responseMessage(context.getResponseMessage()) .tracingSpan(atnSpan); clientBuilder.explicitProvider(methodSecurity.getAuthenticator()); processAuthentication(context, clientBuilder, methodSecurity); } } finally { if (context.isTraceSuccess()) { List<String> logs = new LinkedList<>(); securityContext.user() .ifPresent(user -> logs.add("security.user: " + user.principal().getName())); securityContext.service() .ifPresent(service -> logs.add("security.service: " + service.principal().getName())); finishSpan(atnSpan, logs); } else { HttpUtil.traceError(atnSpan, context.getTraceThrowable(), context.getTraceDescription()); } } }
/** * Check if subject has the specified scopes (must have all of them). * * @param subject subject of a user * @param scopes scopes the subject should have * @return true if the subject has all the specified scopes */ public static boolean inScopes(Subject subject, String... scopes) { List<String> grants = subject.grantsByType("scope").stream().map(Grant::getName).collect(Collectors.toList()); for (String scope : scopes) { if (!grants.contains(scope)) { return false; } } return true; } }
return subject.publicCredential(TokenCredential.class) .map(tokenCredential -> propagate(jwtOutboundTarget, tokenCredential.token())); } else {
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); } }
/** * Provider has authenticated the request and created a principal for a user. * * @param principal principal of the user * @return AuthenticationResponse with information filled * @see #success(Subject) * @see #successService(Subject) * @see #successService(Principal) */ public static AuthenticationResponse success(Principal principal) { return success(Subject.builder() .principal(principal) .build()); }
private OutboundSecurityResponse propagate(JwtOutboundTarget ot, Subject subject) { Map<String, List<String>> headers = new HashMap<>(); Jwk jwk = signKeys.forKeyId(ot.jwkKid) .orElseThrow(() -> new JwtException("Signing JWK with kid: " + ot.jwkKid + " is not defined.")); Principal principal = subject.principal(); Jwt.Builder builder = Jwt.builder(); principal.abacAttributeNames().forEach(name -> { principal.abacAttribute(name).ifPresent(val -> builder.addPayloadClaim(name, val)); }); OptionalHelper.from(principal.abacAttribute("full_name")) .ifPresentOrElse(name -> builder.addPayloadClaim("name", name), () -> builder.removePayloadClaim("name")); builder.subject(principal.id()) .preferredUsername(principal.getName()) .issuer(issuer) .algorithm(jwk.algorithm()); ot.update(builder); Jwt jwt = builder.build(); SignedJwt signed = SignedJwt.sign(jwt, jwk); ot.outboundHandler.header(headers, signed.tokenContent()); return OutboundSecurityResponse.withHeaders(headers); }
List<Grant> userScopes = subject.grantsByType(SCOPE_GRANT_TYPE);
return subject.publicCredential(TokenCredential.class) .map(tokenCredential -> propagate(jwtOutboundTarget, tokenCredential.token())); } else {