All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.c4_soft.springaddons.security.oidc.starter.properties.SpringAddonsOidcClientProperties Maven / Gradle / Ivy

There is a newer version: 8.0-RC1
Show newest version
package com.c4_soft.springaddons.security.oidc.starter.properties;

import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponentsBuilder;

import lombok.Data;

/**
 * Auto-configuration for an OAuth2 client (secured with session, not access token) Security(Web)FilterChain with @Order(Ordered.LOWEST_PRECEDENCE - 1).
 * Typical use-cases are spring-cloud-gateway used as BFF and applications with Thymeleaf or another server-side rendering framework. Default configuration
 * includes: enabled sessions, CSRF protection, "oauth2Login", "logout". securityMatchers must be set for this filter-chain @Bean and its dependencies to be
 * defined. Properties defined here are a complement for spring.security.oauth2.client.* (which are required when enabling spring-addons client
 * filter-chain).
 *
 * @author Jerome Wacongne ch4mp@c4-soft.com
 */
@Data
@ConfigurationProperties
public class SpringAddonsOidcClientProperties {
    public static final String RESPONSE_STATUS_HEADER = "X-RESPONSE-STATUS";

    public static final String POST_AUTHENTICATION_SUCCESS_URI_HEADER = "X-POST-LOGIN-SUCCESS-URI";
    public static final String POST_AUTHENTICATION_SUCCESS_URI_PARAM = "post_login_success_uri";
    public static final String POST_AUTHENTICATION_SUCCESS_URI_SESSION_ATTRIBUTE = POST_AUTHENTICATION_SUCCESS_URI_PARAM;

    public static final String POST_AUTHENTICATION_FAILURE_URI_HEADER = "X-POST-LOGIN-FAILURE-URI";
    public static final String POST_AUTHENTICATION_FAILURE_URI_PARAM = "post_login_failure_uri";
    public static final String POST_AUTHENTICATION_FAILURE_URI_SESSION_ATTRIBUTE = POST_AUTHENTICATION_FAILURE_URI_PARAM;
    public static final String POST_AUTHENTICATION_FAILURE_CAUSE_ATTRIBUTE = "error";

    public static final String POST_LOGOUT_SUCCESS_URI_HEADER = "X-POST-LOGOUT-SUCCESS-URI";
    public static final String POST_LOGOUT_SUCCESS_URI_PARAM = "post_logout_success_uri";

    /**
     * Path matchers for the routes secured with the auto-configured client filter-chain. If left empty, OAuth2 client auto-configuration is disabled. It should
     * include "/login/**" and "/oauth2/**" for login process. Can be set to "/**" to intercept all requests (OAuth2 client only application, no REST API
     * secured with access tokens).
     */
    private List securityMatchers = List.of();

    /**
     * Fully qualified URI of the configured OAuth2 client.
     */
    private URI clientUri = URI.create("/");

    /**
     * Path to the login page. Provide one only in the following cases:
     * 
    *
  • you want to provide your own login @Controller
  • *
  • you want to use port 80 or 8080 with SSL enabled (this will require you to provide with the login @Controller above)
  • *
* If left empty, the default Spring Boot configuration for OAuth2 login is applied */ private Optional loginPath = Optional.empty(); /** * URI containing scheme, host and port where the user should be redirected after a successful login (defaults to the client URI) */ private Optional postLoginRedirectHost = Optional.empty(); /** * Where to redirect the user after successful login */ private Optional postLoginRedirectPath = Optional.empty(); /** * Where to redirect the user after login failure */ private Optional loginErrorRedirectPath = Optional.empty(); /** * HTTP status for redirections in OAuth2 login and logout. You might set this to something in 2xx range (like OK, ACCEPTED, NO_CONTENT, ...) for single * page and mobile applications to handle this redirection as it wishes (change the user-agent, clear some headers, ...). */ private OAuth2RedirectionProperties oauth2Redirections = new OAuth2RedirectionProperties(); public URI getPostLoginRedirectHost() { return postLoginRedirectHost.orElse(clientUri); } public Optional getPostLoginRedirectUri() { if (postLoginRedirectHost.isEmpty() && postLoginRedirectPath.isEmpty()) { return Optional.empty(); } final var uri = UriComponentsBuilder.fromUri(getPostLoginRedirectHost()); postLoginRedirectPath.ifPresent(uri::path); return Optional.of(uri.build(Map.of())); } /** * URI containing scheme, host and port where the user should be redirected after a successful logout (defaults to the client URI) */ private Optional postLogoutRedirectHost = Optional.empty(); /** * Path (relative to clientUri) where the user should be redirected after being logged out from authorization server(s) */ private Optional postLogoutRedirectPath = Optional.empty(); public URI getPostLogoutRedirectHost() { return postLogoutRedirectHost.orElse(clientUri); } public URI getPostLogoutRedirectUri() { var uri = UriComponentsBuilder.fromUri(getPostLogoutRedirectHost()); postLogoutRedirectPath.ifPresent(uri::path); return uri.build(Map.of()); } /** * Map of logout properties indexed by client registration ID (must match a registration in Spring Boot OAuth2 client configuration). * {@link OAuth2LogoutProperties} are configuration for authorization server not strictly following the * RP-Initiated Logout standard, but exposing a logout end-point expecting an * authorized GET request with following request params: *
    *
  • "client-id" (required)
  • *
  • post-logout redirect URI (optional)
  • *
*/ private Map oauth2Logout = new HashMap<>(); /** *

* If true, AOP is used to instrument authorized client repository and keep the principalName current user has for each issuer he authenticates on. *

*

* This is useful only if you allow a user to authenticate on more than one OpenID Provider at a time. For instance, user logs in on Google and on an * authorization server of your own and your client sends direct queries to Google APIs (with an access token issued by Google) and resource servers of your * own (with an access token from your authorization server). *

*/ private boolean multiTenancyEnabled = false; /** * Path matchers for the routes accessible to anonymous requests */ private List permitAll = List.of("/login/**", "/oauth2/**"); /** * CSRF protection configuration for the auto-configured client filter-chain */ private Csrf csrf = Csrf.DEFAULT; /** * When true, PKCE is enabled (by default, Spring enables it only for "public" clients) */ private boolean pkceForced = false; /** * Fine grained CORS configuration * * @deprecated use com.c4-soft.springaddons.oidc.cors instead */ @Deprecated(forRemoval = true) private List cors = List.of(); /** * Additional parameters to send with authorization request, mapped by client registration IDs * * @deprecated use the more concise authorization-params syntax */ @Deprecated private Map> authorizationRequestParams = new HashMap<>(); /** *

* Additional parameters to send with authorization request, mapped by client registration IDs. *

*

* {@link OAuth2AuthorizationRequest#getAdditionalParameters()} return a Map<String, Object>, when it should probably be Map<String, * List<String>>. Also the serializer does not handle collections correctly (serializes using {@link Object#toString()} instead of repeating the * parameter with each value toString()). What spring-addons does is joining the String values with a comma. *

*/ private Map>> authorizationParams = new HashMap<>(); public MultiValueMap getExtraAuthorizationParameters(String registrationId) { return getExtraParameters(registrationId, authorizationRequestParams, authorizationParams); } /** * Additional parameters to send with token request, mapped by client registration IDs * * @deprecated use the more concise token-params syntax */ @Deprecated private Map> tokenRequestParams = new HashMap<>(); /** * Additional parameters to send with authorization request, mapped by client registration IDs */ private Map>> tokenParams = new HashMap<>(); public MultiValueMap getExtraTokenParameters(String registrationId) { return getExtraParameters(registrationId, tokenRequestParams, tokenParams); } private static MultiValueMap getExtraParameters( String registrationId, Map> requestParams, Map>> requestParamsMap) { final var extraParameters = Optional.ofNullable(requestParamsMap.get(registrationId)).map(LinkedMultiValueMap::new).orElse(new LinkedMultiValueMap<>()); for (final var param : requestParams.getOrDefault(registrationId, List.of())) { if (StringUtils.hasText(param.getName())) { extraParameters.add(param.getName(), param.getValue()); } } return extraParameters; } /** * Logout properties for OpenID Providers which do not implement the RP-Initiated Logout spec * * @author Jerome Wacongne ch4mp@c4-soft.com */ @Data @ConfigurationProperties public static class OAuth2LogoutProperties { /** * URI on the authorization server where to redirect the user for logout */ private URI uri; /** * request param name for client-id */ private Optional clientIdRequestParam = Optional.empty(); /** * request param name for post-logout redirect URI (where the user should be redirected after his session is closed on the authorization server) */ private Optional postLogoutUriRequestParam = Optional.empty(); /** * request param name for setting an ID-Token hint */ private Optional idTokenHintRequestParam = Optional.empty(); /** * RP-Initiated Logout is enabled by default. Setting this to false disables it. */ private boolean enabled = true; } private BackChannelLogoutProperties backChannelLogout = new BackChannelLogoutProperties(); @Data @ConfigurationProperties public static class BackChannelLogoutProperties { private boolean enabled = false; /** * The URI for a loop of the Spring client to itself in which it actually ends the user session. Overriding this can be useful to force the scheme and * port in the case where the client is behind a reverse proxy with different scheme and port (default URI uses the original Back-Channel Logout request * scheme and ports). */ private Optional internalLogoutUri = Optional.empty(); } /** * Request parameter * * @author Jerome Wacongne ch4mp@c4-soft.com */ @Data @ConfigurationProperties public static class RequestParam { /** * request parameter name */ private String name; /** * request parameter value */ private String value; } @Data @ConfigurationProperties public static class OAuth2RedirectionProperties { /** * Status for the 1st response in authorization code flow, with location to get authorization code from authorization server */ private HttpStatus preAuthorizationCode = HttpStatus.FOUND; /** * Status for the response after authorization code, with location to the UI */ private HttpStatus postAuthorizationCode = HttpStatus.FOUND; /** * Status for the response after BFF logout, with location to authorization server logout endpoint */ private HttpStatus rpInitiatedLogout = HttpStatus.FOUND; } public Optional getLogoutProperties(String clientRegistrationId) { return Optional.ofNullable(oauth2Logout.get(clientRegistrationId)); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy