@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); }
@Override public CompletionStage<OutboundSecurityResponse> outboundSecurity(ProviderRequest providerRequest, SecurityEnvironment outboundEnv, EndpointConfig outboundConfig) { return CompletableFuture.supplyAsync(() -> signRequest(outboundEnv), providerRequest.securityContext().executorService()); }
/** * Authorize a request based on configuration. * * Authorization cannot be optional. If this method is called, it should always attempt to authorize the current request. * This method will be invoked for inbound requests ONLY. * * @param providerRequest context of this security enforcement/validation * @return response that either permits, denies or abstains from decision * @see AuthorizationResponse#permit() */ public final CompletionStage<AuthorizationResponse> authorize(ProviderRequest providerRequest) { return CompletableFuture.supplyAsync(() -> syncAuthorize(providerRequest), providerRequest.securityContext().executorService()); }
/** * Authenticate a request. * This may be just resolving headers (tokens) or full authentication (basic auth). * Do not throw exception for normal processing (e.g. invalid credentials; you may throw an exception in case of * misconfiguration). * * This method will be invoked for inbound requests ONLY. * * @param providerRequest context of this security enforcement/validation * @return AuthenticationResponse, including the subject for successful authentications * @see AuthenticationResponse#success(io.helidon.security.Subject) */ public final CompletionStage<AuthenticationResponse> authenticate(ProviderRequest providerRequest) { return CompletableFuture .supplyAsync(() -> syncAuthenticate(providerRequest), providerRequest.securityContext().executorService()); }
@Override public boolean isOutboundSupported(ProviderRequest providerRequest, SecurityEnvironment outbondEnv, EndpointConfig outboundEp) { // explicitly overridden username and/or password if (outboundEp.abacAttributeNames().contains(EP_PROPERTY_OUTBOUND_USER)) { return true; } SecurityContext secContext = providerRequest.securityContext(); boolean userSupported = secContext.user() .map(user -> user.privateCredential(UserStore.User.class).isPresent()).orElse(false); boolean serviceSupported = secContext.service() .map(user -> user.privateCredential(UserStore.User.class).isPresent()).orElse(false); return userSupported || serviceSupported; }
/** * Creates necessary updates to headers and entity needed for outbound * security (e.g. identity propagation, s2s security etc.). * This method will be invoked for outbound requests ONLY. * * @param providerRequest context with environment, subject(s) etc. that was received * @param outboundEnv environment for outbound call * @param outboundConfig outbound endpoint configuration * @return response with generated headers and other possible configuration * @see OutboundSecurityResponse#builder() */ public final CompletionStage<OutboundSecurityResponse> outboundSecurity(ProviderRequest providerRequest, SecurityEnvironment outboundEnv, EndpointConfig outboundConfig) { return CompletableFuture.supplyAsync(() -> syncOutbound(providerRequest, outboundEnv, outboundConfig), providerRequest.securityContext().executorService()); }
@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()); }
@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(); } return toPropagate .map(Subject::principal) .map(Principal::id) .map(id -> { Map<String, List<String>> headers = new HashMap<>(); outboundTokenHandler.header(headers, id); return OutboundSecurityResponse.withHeaders(headers); }) .orElse(OutboundSecurityResponse.abstain()); }
@Override public CompletionStage<AuthenticationResponse> authenticate(ProviderRequest providerRequest) { Map<String, List<String>> headers = providerRequest.env().headers(); if ((headers.get("Signature") != null) && acceptHeaders.contains(HttpSignHeader.SIGNATURE)) { return CompletableFuture .supplyAsync(() -> signatureHeader(headers.get("Signature"), providerRequest.env()), providerRequest.securityContext().executorService()); } else if ((headers.get("Authorization") != null) && acceptHeaders.contains(HttpSignHeader.AUTHORIZATION)) { // TODO when authorization header in use and "authorization" is also a // required header to be signed, we must either fail or ignore, as we cannot sign ourselves return CompletableFuture .supplyAsync(() -> authorizeHeader(providerRequest.env()), providerRequest.securityContext().executorService()); } if (optional) { return CompletableFuture.completedFuture(AuthenticationResponse.abstain()); } return CompletableFuture .completedFuture(AuthenticationResponse.failed("Missing header. Accepted headers: " + acceptHeaders)); }
@Override protected AuthenticationResponse syncAuthenticate(ProviderRequest providerRequest) { Optional<String> maybeToken; try { maybeToken = tokenHandler.extractToken(providerRequest.env().headers()); } catch (Exception e) { return failInvalidRequest(e); } SecurityContext sContext = providerRequest.securityContext(); return maybeToken .map(token -> cachedResponse(token, sContext.tracer(), sContext.tracingSpan())) .orElseGet(this::failNoToken); }
Optional<Subject> maybeSubject; if (subjectType == SubjectType.USER) { maybeSubject = providerRequest.securityContext().user(); } else { maybeSubject = providerRequest.securityContext().service();
Optional<Subject> maybeSubject; if (subjectType == SubjectType.USER) { maybeSubject = providerRequest.securityContext().user(); } else { maybeSubject = providerRequest.securityContext().service();
SecurityContext secContext = providerRequest.securityContext();
@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(); } return toPropagate .map(Subject::principal) .map(Principal::id) .map(id -> { Map<String, List<String>> headers = new HashMap<>(); outboundTokenHandler.header(headers, id); return OutboundSecurityResponse.withHeaders(headers); }) .orElse(OutboundSecurityResponse.abstain()); }
Optional<Subject> maybeSubject; if (subjectType == SubjectType.USER) { maybeSubject = providerRequest.securityContext().user(); } else { maybeSubject = providerRequest.securityContext().service();
Optional<Subject> maybeSubject; if (subjectType == SubjectType.USER) { maybeSubject = providerRequest.securityContext().user(); } else { maybeSubject = providerRequest.securityContext().service();