@Override protected AuthenticationResponse syncAuthenticate(ProviderRequest providerRequest) { if (!authenticate) { return AuthenticationResponse.abstain(); } Optional<String> username = atnTokenHandler.extractToken(providerRequest.env().headers()); return username .map(Principal::create) .map(principal -> { if (subjectType == SubjectType.USER) { return AuthenticationResponse.success(principal); } else { return AuthenticationResponse.successService(principal); } }) .orElseGet(() -> { if (optional) { return AuthenticationResponse.abstain(); } else { return AuthenticationResponse.failed("Header not available or in a wrong format"); } } ); }
if (!flag.isValid(thisResponse.status())) { switch (thisResponse.status()) { case SUCCESS: case SUCCESS_FINISH: case ABSTAIN: AuthenticationResponse.Builder builder = AuthenticationResponse.builder(); builder.status(SecurityResponse.SecurityStatus.FAILURE); builder.description("Composite flag forbids this response: " + thisResponse.status()); thisResponse.description().map(builder::description); thisResponse.throwable().map(builder::throwable); throw new AsyncAtnException(builder.build()); case FAILURE: thisResponse.status() == SecurityResponse.SecurityStatus.SUCCESS)) { if (prevResponse.status() == SecurityResponse.SecurityStatus.ABSTAIN) { return thisResponse.status().isSuccess() ? thisResponse : prevResponse; if (!thisResponse.status().isSuccess()) { return prevResponse; AuthenticationResponse.Builder responseBuilder = AuthenticationResponse.builder(); OptionalHelper.from(prevResponse.user() .map(user -> combine(user, thisResponse.user()))) .or(thisResponse::user) .asOptional()
@Override protected AuthenticationResponse syncAuthenticate(ProviderRequest providerRequest) { if (!authenticate) { return AuthenticationResponse.abstain(); } List<LoginConfig> loginConfigs = providerRequest.endpointConfig() .combineAnnotations(LoginConfig.class, EndpointConfig.AnnotationScope.APPLICATION); try { return loginConfigs.stream() .filter(JwtAuthAnnotationAnalyzer::isMpJwt) .findFirst() .map(loginConfig -> authenticate(providerRequest, loginConfig)) .orElseGet(AuthenticationResponse::abstain); } catch (java.lang.SecurityException e) { return AuthenticationResponse.failed("Failed to process authentication header", e); } }
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 AuthenticationResponse syncAuthenticate(ProviderRequest providerRequest) { if (!authenticate) { return AuthenticationResponse.abstain(); } return atnTokenHandler.extractToken(providerRequest.env().headers()) .map(token -> { SignedJwt signedJwt = SignedJwt.parseToken(token); Errors errors = signedJwt.verifySignature(verifyKeys); if (errors.isValid()) { Jwt jwt = signedJwt.getJwt(); // verify the audience is correct Errors validate = jwt.validate(null, expectedAudience); if (validate.isValid()) { return AuthenticationResponse.success(buildSubject(jwt, signedJwt)); } else { return AuthenticationResponse.failed("Audience is invalid or missing: " + expectedAudience); } } else { return AuthenticationResponse.failed(errors.toString()); } }).orElseGet(() -> { if (optional) { return AuthenticationResponse.abstain(); } else { return AuthenticationResponse.failed("Header not available or in a wrong format"); } }); }
@Override public CompletionStage<AuthenticationResponse> authenticate(ProviderRequest providerRequest) { CompletionStage<AuthenticationResponse> previous = CompletableFuture.completedFuture(AuthenticationResponse.abstain()); return ((AsyncAtnException) cause).response; return AuthenticationResponse.failed("Failed processing: " + throwable.getMessage(), throwable); }).thenApply(authenticationResponse -> { if (authenticationResponse.status() == SecurityResponse.SecurityStatus.ABSTAIN) { return AuthenticationResponse.abstain();
private AuthenticationResponse validateSignature(SecurityEnvironment env, HttpSignature httpSignature, InboundClientDefinition clientDefinition) { // validate algorithm Optional<String> validationResult = httpSignature.validate(env, clientDefinition, inboundRequiredHeaders.headers(env.method(), env.headers())); if (validationResult.isPresent()) { return AuthenticationResponse.failed(validationResult.get()); } Principal principal = Principal.builder() .name(clientDefinition.principalName()) .addAttribute(ATTRIB_NAME_KEY_ID, clientDefinition.keyId()) .build(); Subject subject = Subject.builder() .principal(principal) .build(); if (clientDefinition.subjectType() == SubjectType.USER) { return AuthenticationResponse.success(subject); } else { return AuthenticationResponse.successService(subject); } }
private AuthenticationResponse failNoToken() { if (optional) { LOGGER.log(Level.FINE, "Failed to authenticate Google token, token not present"); return AuthenticationResponse.abstain(); } return AuthenticationResponse.builder() .statusCode(401) .responseHeader(HEADER_AUTHENTICATION_REQUIRED, buildChallenge(null)) .status(AuthenticationResponse.SecurityStatus.FAILURE) .description("Missing authorization header") .build(); }
private AuthenticationResponse authorizeHeader(SecurityEnvironment env) { List<String> authorization = env.headers().get("Authorization"); AuthenticationResponse response = null; // attempt to validate each authorization, first one that succeeds will finish processing and return for (String authorizationValue : authorization) { if (authorizationValue.toLowerCase().startsWith("signature ")) { response = signatureHeader(CollectionsHelper.listOf(authorizationValue.substring("singature ".length())), env); if (response.status().isSuccess()) { // that was a good header, let's return the response return response; } } } // we have reached the end - all headers validated, none fit, fail or abstain if (optional) { return AuthenticationResponse.abstain(); } // challenge return challenge(env, (null == response) ? "No Signature authorization header" : response.description().orElse("Unknown problem")); }
/** * Provider returning this response is not capable to make a decision (e.g. the user format is not supported). * * @return AuthenticationResponse with information filled */ public static AuthenticationResponse abstain() { return builder().status(SecurityStatus.ABSTAIN).build(); }
return AuthenticationResponse.success(buildSubject(user)); } else { return AuthenticationResponse.successService(buildSubject(user));
SecurityResponse.SecurityStatus responseStatus = response.status(); } else { context.setTraceSuccess(false); context.setTraceDescription(response.description().orElse(responseStatus.toString())); context.setTraceThrowable(response.throwable().orElse(null)); context.setShouldFinish(true); int status = response.statusCode().orElse(Response.Status.UNAUTHORIZED.getStatusCode()); abortRequest(context, response, status, CollectionsHelper.mapOf()); int status = response.statusCode().orElse(Response.Status.OK.getStatusCode()); abortRequest(context, response, status, CollectionsHelper.mapOf()); } else { context.setTraceSuccess(false); context.setTraceDescription(response.description().orElse(responseStatus.toString())); context.setShouldFinish(true); abortRequest(context, logger().finest("Authentication failed, but was optional, so assuming anonymous"); } else { context.setTraceDescription(response.description().orElse(responseStatus.toString())); context.setTraceThrowable(response.throwable().orElse(null)); context.setTraceSuccess(false); abortRequest(context, default: context.setTraceSuccess(false);
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(); }
/** * 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()); }
.addProvider(AbacProvider.create()) .addAuthenticationProvider(providerRequest -> CompletableFuture .completedFuture(AuthenticationResponse.failed("No provider configured"))) .build();
/** * Provider has authenticated the request and created a principal for a service (or a client). * * @param principal principal of the service * @return AuthenticationResponse with information filled * @see #successService(Subject) * @see #success(Subject) * @see #success(Principal) */ public static AuthenticationResponse successService(Principal principal) { return successService(Subject.builder() .principal(principal) .build()); }
@Override public CompletionStage<AuthenticationResponse> map(ProviderRequest authenticatedRequest, AuthenticationResponse previousResponse) { // this only supports users return previousResponse.user().map(subject -> enhance(subject, previousResponse)) .orElseGet(() -> CompletableFuture.completedFuture(previousResponse)); }
AuthenticationResponse authenticate(ProviderRequest providerRequest, LoginConfig loginConfig) { return atnTokenHandler.extractToken(providerRequest.env().headers()) .map(token -> { SignedJwt signedJwt = SignedJwt.parseToken(token); Errors errors = signedJwt.verifySignature(verifyKeys, defaultJwk); if (errors.isValid()) { Jwt jwt = signedJwt.getJwt(); // verify the audience is correct Errors validate = jwt.validate(expectedIssuer, expectedAudience); if (validate.isValid()) { return AuthenticationResponse.success(buildSubject(jwt, signedJwt)); } else { return AuthenticationResponse.failed("Audience is invalid or missing: " + expectedAudience); } } else { return AuthenticationResponse.failed(errors.toString()); } }).orElseGet(() -> { if (optional) { return AuthenticationResponse.abstain(); } else { return AuthenticationResponse.failed("Header not available or in a wrong format"); } }); }
private AuthenticationResponse signatureHeader(List<String> signatures, SecurityEnvironment env) { /* Signature keyId="rsa-key-1",algorithm="rsa-sha256", headers="(request-target) host date digest content-length", signature="Base64(RSA-SHA256(signing string))" */ String lastError = signatures.isEmpty() ? "No signature values for Signature header" : null; for (String signature : signatures) { HttpSignature httpSignature = HttpSignature.fromHeader(signature); Optional<String> validate = httpSignature.validate(); if (validate.isPresent()) { lastError = validate.get(); } else { //this is a valid signature object, let's validate against key InboundClientDefinition clientDefinition = inboundKeys.get(httpSignature.getKeyId()); if (null == clientDefinition) { lastError = "Client definition for client with key " + httpSignature.getKeyId() + " not found"; continue; } //now we have a signature with a valid keyId - if validation fails, we fail return validateSignature(env, httpSignature, clientDefinition); } } if (optional) { return AuthenticationResponse.abstain(); } else { return AuthenticationResponse.failed(lastError); } }