diff --git a/spring-addons-starter-oidc/src/main/java/com/c4_soft/springaddons/security/oidc/starter/properties/condition/bean/DefaultAuthenticationFailureHandlerCondition.java b/spring-addons-starter-oidc/src/main/java/com/c4_soft/springaddons/security/oidc/starter/properties/condition/bean/DefaultAuthenticationFailureHandlerCondition.java index 85a6a9355..961771587 100644 --- a/spring-addons-starter-oidc/src/main/java/com/c4_soft/springaddons/security/oidc/starter/properties/condition/bean/DefaultAuthenticationFailureHandlerCondition.java +++ b/spring-addons-starter-oidc/src/main/java/com/c4_soft/springaddons/security/oidc/starter/properties/condition/bean/DefaultAuthenticationFailureHandlerCondition.java @@ -1,50 +1,22 @@ package com.c4_soft.springaddons.security.oidc.starter.properties.condition.bean; -import org.springframework.boot.autoconfigure.condition.AllNestedConditions; -import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.NoneNestedConditions; -import org.springframework.context.annotation.Conditional; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler; -public class DefaultAuthenticationFailureHandlerCondition extends AllNestedConditions { +public class DefaultAuthenticationFailureHandlerCondition extends NoneNestedConditions { - public DefaultAuthenticationFailureHandlerCondition() { - super(ConfigurationPhase.REGISTER_BEAN); - } + public DefaultAuthenticationFailureHandlerCondition() { + super(ConfigurationPhase.REGISTER_BEAN); + } - @Conditional(NoAuthenticationFailureHandlerCondition.class) - static class AuthenticationFailureHandlerMissingCondition {} + @ConditionalOnBean(AuthenticationFailureHandler.class) + static class AuthenticationFailureHandlerProvidedCondition { + } - @Conditional(PostLoginRedirectUriCondition.class) - static class PostLoginRedirectUriProvidedCondition {} - - static class NoAuthenticationFailureHandlerCondition extends NoneNestedConditions { - - public NoAuthenticationFailureHandlerCondition() { - super(ConfigurationPhase.REGISTER_BEAN); - } - - @ConditionalOnBean(AuthenticationFailureHandler.class) - static class AuthenticationFailureHandlerProvidedCondition {} - - @ConditionalOnBean(ServerAuthenticationFailureHandler.class) - static class ServerAuthenticationFailureHandlerProvidedCondition {} - } - - static class PostLoginRedirectUriCondition extends AnyNestedCondition { - - public PostLoginRedirectUriCondition() { - super(ConfigurationPhase.REGISTER_BEAN); - } - - @ConditionalOnProperty(name = "com.c4-soft.springaddons.oidc.client.post-login-redirect-host") - static class PostLoginRedirectHostCondition {} - - @ConditionalOnProperty(name = "com.c4-soft.springaddons.oidc.client.post-login-redirect-path") - static class PostLoginRedirectPathCondition {} - } + @ConditionalOnBean(ServerAuthenticationFailureHandler.class) + static class ServerAuthenticationFailureHandlerProvidedCondition { + } } diff --git a/spring-addons-starter-oidc/src/main/java/com/c4_soft/springaddons/security/oidc/starter/properties/condition/bean/DefaultAuthenticationSuccessHandlerCondition.java b/spring-addons-starter-oidc/src/main/java/com/c4_soft/springaddons/security/oidc/starter/properties/condition/bean/DefaultAuthenticationSuccessHandlerCondition.java index 7476924d9..a4fe0c30d 100644 --- a/spring-addons-starter-oidc/src/main/java/com/c4_soft/springaddons/security/oidc/starter/properties/condition/bean/DefaultAuthenticationSuccessHandlerCondition.java +++ b/spring-addons-starter-oidc/src/main/java/com/c4_soft/springaddons/security/oidc/starter/properties/condition/bean/DefaultAuthenticationSuccessHandlerCondition.java @@ -1,49 +1,21 @@ package com.c4_soft.springaddons.security.oidc.starter.properties.condition.bean; -import org.springframework.boot.autoconfigure.condition.AllNestedConditions; -import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.NoneNestedConditions; -import org.springframework.context.annotation.Conditional; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler; -public class DefaultAuthenticationSuccessHandlerCondition extends AllNestedConditions { +public class DefaultAuthenticationSuccessHandlerCondition extends NoneNestedConditions { - public DefaultAuthenticationSuccessHandlerCondition() { - super(ConfigurationPhase.REGISTER_BEAN); - } + public DefaultAuthenticationSuccessHandlerCondition() { + super(ConfigurationPhase.REGISTER_BEAN); + } - @Conditional(NoAuthenticationSuccessHandlerCondition.class) - static class AuthenticationSuccessHandlerMissingCondition {} + @ConditionalOnBean(AuthenticationSuccessHandler.class) + static class AuthenticationSuccessHandlerProvidedCondition { + } - @Conditional(PostLoginRedirectUriCondition.class) - static class PostLoginRedirectUriProvidedCondition {} - - static class NoAuthenticationSuccessHandlerCondition extends NoneNestedConditions { - - public NoAuthenticationSuccessHandlerCondition() { - super(ConfigurationPhase.REGISTER_BEAN); - } - - @ConditionalOnBean(AuthenticationSuccessHandler.class) - static class AuthenticationSuccessHandlerProvidedCondition {} - - @ConditionalOnBean(ServerAuthenticationSuccessHandler.class) - static class ServerAuthenticationSuccessHandlerProvidedCondition {} - } - - static class PostLoginRedirectUriCondition extends AnyNestedCondition { - - public PostLoginRedirectUriCondition() { - super(ConfigurationPhase.REGISTER_BEAN); - } - - @ConditionalOnProperty(name = "com.c4-soft.springaddons.oidc.client.post-login-redirect-host") - static class PostLoginRedirectHostCondition {} - - @ConditionalOnProperty(name = "com.c4-soft.springaddons.oidc.client.post-login-redirect-path") - static class PostLoginRedirectPathCondition {} - } + @ConditionalOnBean(ServerAuthenticationSuccessHandler.class) + static class ServerAuthenticationSuccessHandlerProvidedCondition { + } } diff --git a/spring-addons-starter-oidc/src/main/java/com/c4_soft/springaddons/security/oidc/starter/reactive/client/SpringAddonsServerOAuth2AuthorizationRequestResolver.java b/spring-addons-starter-oidc/src/main/java/com/c4_soft/springaddons/security/oidc/starter/reactive/client/SpringAddonsServerOAuth2AuthorizationRequestResolver.java index 3bac1b123..644f5b6f0 100644 --- a/spring-addons-starter-oidc/src/main/java/com/c4_soft/springaddons/security/oidc/starter/reactive/client/SpringAddonsServerOAuth2AuthorizationRequestResolver.java +++ b/spring-addons-starter-oidc/src/main/java/com/c4_soft/springaddons/security/oidc/starter/reactive/client/SpringAddonsServerOAuth2AuthorizationRequestResolver.java @@ -27,134 +27,118 @@ /** * Serves three purposes: * * The post-login URIs are used by the default {@link ServerAuthenticationSuccessHandler} and {@link ServerAuthenticationFailureHandler} * * @author Jerome Wacongne ch4mp@c4-soft.com - * @see SpringAddonsOidcClientProperties for header and request parameter constants definitions - * @see SpringAddonsOauth2ServerAuthenticationSuccessHandler - * @see SpringAddonsOauth2ServerAuthenticationFailureHandler + * @see SpringAddonsOidcClientProperties for header and request parameter constants definitions + * @see SpringAddonsOauth2ServerAuthenticationSuccessHandler + * @see SpringAddonsOauth2ServerAuthenticationFailureHandler */ public class SpringAddonsServerOAuth2AuthorizationRequestResolver extends DefaultServerOAuth2AuthorizationRequestResolver { - private static final Pattern authorizationRequestPattern = Pattern.compile("\\/oauth2\\/authorization\\/([^\\/]+)"); - private static final Consumer noOpCustomizer = builder -> {}; - - private final URI clientUri; - private final Map> authRequestCustomizers; - - public SpringAddonsServerOAuth2AuthorizationRequestResolver( - ReactiveClientRegistrationRepository clientRegistrationRepository, - SpringAddonsOidcClientProperties addonsClientProperties) { - super(clientRegistrationRepository); - this.clientUri = addonsClientProperties.getClientUri(); - authRequestCustomizers = addonsClientProperties.getAuthorizationRequestParams().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> { - final var params = addonsClientProperties.getAuthorizationRequestParams().get(e.getKey()); - return e.getValue() == null ? null : requestParamAuthorizationRequestCustomizer(params); - })); - } - - private Mono savePostLoginUrisInSession(ServerWebExchange exchange) { - return exchange.getSession().map(session -> { - Optional - .ofNullable( - Optional - .ofNullable(exchange.getRequest().getHeaders().getFirst(SpringAddonsOidcClientProperties.POST_AUTHENTICATION_SUCCESS_URI_HEADER)) - .orElse( - Optional - .ofNullable( - exchange.getRequest().getQueryParams().getFirst(SpringAddonsOidcClientProperties.POST_AUTHENTICATION_SUCCESS_URI_PARAM)) - .orElse(null))) - .filter(StringUtils::hasText) - .map(URI::create) - .ifPresent(postLoginSuccessUri -> { - session.getAttributes().put(SpringAddonsOidcClientProperties.POST_AUTHENTICATION_SUCCESS_URI_SESSION_ATTRIBUTE, postLoginSuccessUri); - }); - - Optional - .ofNullable( - Optional - .ofNullable(exchange.getRequest().getHeaders().getFirst(SpringAddonsOidcClientProperties.POST_AUTHENTICATION_FAILURE_URI_HEADER)) - .orElse( - Optional - .ofNullable( - exchange.getRequest().getQueryParams().getFirst(SpringAddonsOidcClientProperties.POST_AUTHENTICATION_FAILURE_URI_PARAM)) - .orElse(null))) - .filter(StringUtils::hasText) - .map(URI::create) - .ifPresent(postLoginFailureUri -> { - session.getAttributes().put(SpringAddonsOidcClientProperties.POST_AUTHENTICATION_FAILURE_URI_SESSION_ATTRIBUTE, postLoginFailureUri); - }); - - return session; - }); - } - - private OAuth2AuthorizationRequest postProcess(OAuth2AuthorizationRequest request) { - final var modified = OAuth2AuthorizationRequest.from(request); - - final var original = URI.create(request.getRedirectUri()); - final var redirectUri = UriComponentsBuilder - .fromUri(clientUri) - .path(original.getPath()) - .query(original.getQuery()) - .fragment(original.getFragment()) - .build() - .toString(); - modified.redirectUri(redirectUri); - - return modified.build(); - } - - @Override - public Mono resolve(ServerWebExchange exchange) { - setAuthorizationRequestCustomizer(authRequestCustomizer(exchange)); - return savePostLoginUrisInSession(exchange).then(super.resolve(exchange).map(this::postProcess)); - } - - @Override - public Mono resolve(ServerWebExchange exchange, String clientRegistrationId) { - setAuthorizationRequestCustomizer(authRequestCustomizer(clientRegistrationId)); - return savePostLoginUrisInSession(exchange).then(super.resolve(exchange, clientRegistrationId).map(this::postProcess)); - } - - Consumer authRequestCustomizer(ServerWebExchange exchange) { - return authRequestCustomizer(resolveRegistrationId(exchange)); - } - - Consumer authRequestCustomizer(String registrationId) { - if (registrationId == null) { - return noOpCustomizer; - } - return authRequestCustomizers.getOrDefault(registrationId, noOpCustomizer); - } - - static String resolveRegistrationId(ServerWebExchange exchange) { - final var requestPath = Optional.ofNullable(exchange.getRequest()).map(ServerHttpRequest::getPath).map(RequestPath::toString).orElse(""); - return resolveRegistrationId(requestPath); - } - - static String resolveRegistrationId(String requestPath) { - final var matcher = authorizationRequestPattern.matcher(requestPath); - return matcher.matches() ? matcher.group(1) : null; - } - - private static Consumer requestParamAuthorizationRequestCustomizer(RequestParam[] additionalParams) { - return customizer -> customizer.authorizationRequestUri(authorizationRequestUri -> { - for (var reqParam : additionalParams) { - authorizationRequestUri.queryParam(reqParam.getName(), reqParam.getValue()); - } - return authorizationRequestUri.build(); - }); - } + private static final Pattern authorizationRequestPattern = Pattern.compile("\\/oauth2\\/authorization\\/([^\\/]+)"); + private static final Consumer noOpCustomizer = builder -> { + }; + + private final URI clientUri; + private final Map> authRequestCustomizers; + + public SpringAddonsServerOAuth2AuthorizationRequestResolver( + ReactiveClientRegistrationRepository clientRegistrationRepository, + SpringAddonsOidcClientProperties addonsClientProperties) { + super(clientRegistrationRepository); + this.clientUri = addonsClientProperties.getClientUri(); + authRequestCustomizers = addonsClientProperties.getAuthorizationRequestParams().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> { + final var params = addonsClientProperties.getAuthorizationRequestParams().get(e.getKey()); + return e.getValue() == null ? null : requestParamAuthorizationRequestCustomizer(params); + })); + } + + private Mono savePostLoginUrisInSession(ServerWebExchange exchange) { + final var request = exchange.getRequest(); + final var headers = request.getHeaders(); + final var params = request.getQueryParams(); + return exchange.getSession().map(session -> { + Optional.ofNullable( + Optional.ofNullable(headers.getFirst(SpringAddonsOidcClientProperties.POST_AUTHENTICATION_SUCCESS_URI_HEADER)) + .orElse(Optional.ofNullable(params.getFirst(SpringAddonsOidcClientProperties.POST_AUTHENTICATION_SUCCESS_URI_PARAM)).orElse(null))) + .filter(StringUtils::hasText).map(URI::create).ifPresent(postLoginSuccessUri -> { + session.getAttributes().put(SpringAddonsOidcClientProperties.POST_AUTHENTICATION_SUCCESS_URI_SESSION_ATTRIBUTE, postLoginSuccessUri); + }); + + Optional.ofNullable( + Optional.ofNullable(headers.getFirst(SpringAddonsOidcClientProperties.POST_AUTHENTICATION_FAILURE_URI_HEADER)) + .orElse(Optional.ofNullable(params.getFirst(SpringAddonsOidcClientProperties.POST_AUTHENTICATION_FAILURE_URI_PARAM)).orElse(null))) + .filter(StringUtils::hasText).map(URI::create).ifPresent(postLoginFailureUri -> { + session.getAttributes().put(SpringAddonsOidcClientProperties.POST_AUTHENTICATION_FAILURE_URI_SESSION_ATTRIBUTE, postLoginFailureUri); + }); + + return session; + }); + } + + private OAuth2AuthorizationRequest postProcess(OAuth2AuthorizationRequest request) { + final var modified = OAuth2AuthorizationRequest.from(request); + + final var original = URI.create(request.getRedirectUri()); + final var redirectUri = + UriComponentsBuilder.fromUri(clientUri).path(original.getPath()).query(original.getQuery()).fragment(original.getFragment()).build().toString(); + modified.redirectUri(redirectUri); + + return modified.build(); + } + + @Override + public Mono resolve(ServerWebExchange exchange) { + setAuthorizationRequestCustomizer(authRequestCustomizer(exchange)); + return savePostLoginUrisInSession(exchange).then(super.resolve(exchange).map(this::postProcess)); + } + + @Override + public Mono resolve(ServerWebExchange exchange, String clientRegistrationId) { + setAuthorizationRequestCustomizer(authRequestCustomizer(clientRegistrationId)); + return savePostLoginUrisInSession(exchange).then(super.resolve(exchange, clientRegistrationId).map(this::postProcess)); + } + + Consumer authRequestCustomizer(ServerWebExchange exchange) { + return authRequestCustomizer(resolveRegistrationId(exchange)); + } + + Consumer authRequestCustomizer(String registrationId) { + if (registrationId == null) { + return noOpCustomizer; + } + return authRequestCustomizers.getOrDefault(registrationId, noOpCustomizer); + } + + static String resolveRegistrationId(ServerWebExchange exchange) { + final var requestPath = Optional.ofNullable(exchange.getRequest()).map(ServerHttpRequest::getPath).map(RequestPath::toString).orElse(""); + return resolveRegistrationId(requestPath); + } + + static String resolveRegistrationId(String requestPath) { + final var matcher = authorizationRequestPattern.matcher(requestPath); + return matcher.matches() ? matcher.group(1) : null; + } + + private static Consumer requestParamAuthorizationRequestCustomizer(RequestParam[] additionalParams) { + return customizer -> customizer.authorizationRequestUri(authorizationRequestUri -> { + for (var reqParam : additionalParams) { + authorizationRequestUri.queryParam(reqParam.getName(), reqParam.getValue()); + } + return authorizationRequestUri.build(); + }); + } }