diff --git a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java index ef388d66ff..c899a5e4a7 100644 --- a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java +++ b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java @@ -53,8 +53,8 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; import org.springframework.security.oauth2.client.userinfo.DefaultReactiveOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.ReactiveOAuth2UserService; -import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectWebFilter; -import org.springframework.security.oauth2.client.web.ServerOAuth2LoginAuthenticationTokenConverter; +import org.springframework.security.oauth2.client.web.server.OAuth2AuthorizationRequestRedirectWebFilter; +import org.springframework.security.oauth2.client.web.server.ServerOAuth2LoginAuthenticationTokenConverter; import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder; import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder; import org.springframework.security.oauth2.server.resource.authentication.JwtReactiveAuthenticationManager; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectWebFilter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilter.java similarity index 95% rename from oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectWebFilter.java rename to oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilter.java index ae89c61498..5020ecd968 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectWebFilter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.security.oauth2.client.web; +package org.springframework.security.oauth2.client.web.server; import java.net.URI; import java.util.Base64; @@ -29,6 +29,7 @@ import org.springframework.security.oauth2.client.ClientAuthorizationRequiredExc import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository; import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; @@ -89,8 +90,8 @@ public class OAuth2AuthorizationRequestRedirectWebFilter implements WebFilter { private final ReactiveClientRegistrationRepository clientRegistrationRepository; private final ServerRedirectStrategy authorizationRedirectStrategy = new DefaultServerRedirectStrategy(); private final StringKeyGenerator stateGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder()); - private ReactiveAuthorizationRequestRepository authorizationRequestRepository = - new WebSessionOAuth2ReactiveAuthorizationRequestRepository(); + private ServerAuthorizationRequestRepository authorizationRequestRepository = + new WebSessionOAuth2ServerAuthorizationRequestRepository(); /** * Constructs an {@code OAuth2AuthorizationRequestRedirectFilter} using the provided parameters. @@ -122,7 +123,8 @@ public class OAuth2AuthorizationRequestRedirectWebFilter implements WebFilter { * * @param authorizationRequestRepository the repository used for storing {@link OAuth2AuthorizationRequest}'s */ - public final void setAuthorizationRequestRepository(ReactiveAuthorizationRequestRepository authorizationRequestRepository) { + public final void setAuthorizationRequestRepository( + ServerAuthorizationRequestRepository authorizationRequestRepository) { Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null"); this.authorizationRequestRepository = authorizationRequestRepository; } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationResponseUtils.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationResponseUtils.java new file mode 100644 index 0000000000..6c75b45e10 --- /dev/null +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationResponseUtils.java @@ -0,0 +1,85 @@ +/* + * Copyright 2002-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.security.oauth2.client.web.server; + +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponse; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; + +import java.util.Map; + +/** + * Utility methods for an OAuth 2.0 Authorization Response. + * + * @author Joe Grandja + * @since 5.1 + * @see OAuth2AuthorizationResponse + */ +final class OAuth2AuthorizationResponseUtils { + + private OAuth2AuthorizationResponseUtils() { + } + + static MultiValueMap toMultiMap(Map map) { + MultiValueMap params = new LinkedMultiValueMap<>(map.size()); + map.forEach((key, values) -> { + if (values.length > 0) { + for (String value : values) { + params.add(key, value); + } + } + }); + return params; + } + + static boolean isAuthorizationResponse(MultiValueMap request) { + return isAuthorizationResponseSuccess(request) || isAuthorizationResponseError(request); + } + + static boolean isAuthorizationResponseSuccess(MultiValueMap request) { + return StringUtils.hasText(request.getFirst(OAuth2ParameterNames.CODE)) && + StringUtils.hasText(request.getFirst(OAuth2ParameterNames.STATE)); + } + + static boolean isAuthorizationResponseError(MultiValueMap request) { + return StringUtils.hasText(request.getFirst(OAuth2ParameterNames.ERROR)) && + StringUtils.hasText(request.getFirst(OAuth2ParameterNames.STATE)); + } + + static OAuth2AuthorizationResponse convert(MultiValueMap request, String redirectUri) { + String code = request.getFirst(OAuth2ParameterNames.CODE); + String errorCode = request.getFirst(OAuth2ParameterNames.ERROR); + String state = request.getFirst(OAuth2ParameterNames.STATE); + + if (StringUtils.hasText(code)) { + return OAuth2AuthorizationResponse.success(code) + .redirectUri(redirectUri) + .state(state) + .build(); + } else { + String errorDescription = request.getFirst(OAuth2ParameterNames.ERROR_DESCRIPTION); + String errorUri = request.getFirst(OAuth2ParameterNames.ERROR_URI); + return OAuth2AuthorizationResponse.error(errorCode) + .redirectUri(redirectUri) + .errorDescription(errorDescription) + .errorUri(errorUri) + .state(state) + .build(); + } + } +} diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/ReactiveAuthorizationRequestRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerAuthorizationRequestRepository.java similarity index 85% rename from oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/ReactiveAuthorizationRequestRepository.java rename to oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerAuthorizationRequestRepository.java index 05ebd64770..eee622c05a 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/ReactiveAuthorizationRequestRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerAuthorizationRequestRepository.java @@ -14,8 +14,11 @@ * limitations under the License. */ -package org.springframework.security.oauth2.client.web; +package org.springframework.security.oauth2.client.web.server; +import org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository; +import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter; +import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; import org.springframework.web.server.ServerWebExchange; @@ -38,7 +41,7 @@ import reactor.core.publisher.Mono; * * @param The type of OAuth 2.0 Authorization Request */ -public interface ReactiveAuthorizationRequestRepository { +public interface ServerAuthorizationRequestRepository { /** * Returns the {@link OAuth2AuthorizationRequest} associated to the provided {@code HttpServletRequest} diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/ServerOAuth2LoginAuthenticationTokenConverter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2LoginAuthenticationTokenConverter.java similarity index 89% rename from oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/ServerOAuth2LoginAuthenticationTokenConverter.java rename to oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2LoginAuthenticationTokenConverter.java index 10ed1b4da9..492bc68def 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/ServerOAuth2LoginAuthenticationTokenConverter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2LoginAuthenticationTokenConverter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.security.oauth2.client.web; +package org.springframework.security.oauth2.client.web.server; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationToken; @@ -47,8 +47,8 @@ public class ServerOAuth2LoginAuthenticationTokenConverter static final String CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE = "client_registration_not_found"; - private ReactiveAuthorizationRequestRepository authorizationRequestRepository = - new WebSessionOAuth2ReactiveAuthorizationRequestRepository(); + private ServerAuthorizationRequestRepository authorizationRequestRepository = + new WebSessionOAuth2ServerAuthorizationRequestRepository(); private final ReactiveClientRegistrationRepository clientRegistrationRepository; @@ -59,12 +59,12 @@ public class ServerOAuth2LoginAuthenticationTokenConverter } /** - * Sets the {@link ReactiveAuthorizationRequestRepository} to be used. The default is - * {@link WebSessionOAuth2ReactiveAuthorizationRequestRepository}. + * Sets the {@link ServerAuthorizationRequestRepository} to be used. The default is + * {@link WebSessionOAuth2ServerAuthorizationRequestRepository}. * @param authorizationRequestRepository the repository to use. */ public void setAuthorizationRequestRepository( - ReactiveAuthorizationRequestRepository authorizationRequestRepository) { + ServerAuthorizationRequestRepository authorizationRequestRepository) { Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null"); this.authorizationRequestRepository = authorizationRequestRepository; } @@ -110,6 +110,7 @@ public class ServerOAuth2LoginAuthenticationTokenConverter .build() .toUriString(); - return OAuth2AuthorizationResponseUtils.convert(queryParams, redirectUri); + return OAuth2AuthorizationResponseUtils + .convert(queryParams, redirectUri); } } diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/WebSessionOAuth2ReactiveAuthorizationRequestRepository.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepository.java similarity index 90% rename from oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/WebSessionOAuth2ReactiveAuthorizationRequestRepository.java rename to oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepository.java index aa8b4302a6..ceed2160e7 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/WebSessionOAuth2ReactiveAuthorizationRequestRepository.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepository.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package org.springframework.security.oauth2.client.web; +package org.springframework.security.oauth2.client.web.server; import java.util.HashMap; import java.util.Map; import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; import org.springframework.util.Assert; @@ -29,7 +30,7 @@ import org.springframework.web.server.WebSession; import reactor.core.publisher.Mono; /** - * An implementation of an {@link ReactiveAuthorizationRequestRepository} that stores + * An implementation of an {@link ServerAuthorizationRequestRepository} that stores * {@link OAuth2AuthorizationRequest} in the {@code WebSession}. * * @author Rob Winch @@ -37,10 +38,11 @@ import reactor.core.publisher.Mono; * @see AuthorizationRequestRepository * @see OAuth2AuthorizationRequest */ -public final class WebSessionOAuth2ReactiveAuthorizationRequestRepository implements ReactiveAuthorizationRequestRepository { +public final class WebSessionOAuth2ServerAuthorizationRequestRepository + implements ServerAuthorizationRequestRepository { private static final String DEFAULT_AUTHORIZATION_REQUEST_ATTR_NAME = - WebSessionOAuth2ReactiveAuthorizationRequestRepository.class.getName() + ".AUTHORIZATION_REQUEST"; + WebSessionOAuth2ServerAuthorizationRequestRepository.class.getName() + ".AUTHORIZATION_REQUEST"; private final String sessionAttributeName = DEFAULT_AUTHORIZATION_REQUEST_ATTR_NAME; diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectWebFilterTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilterTests.java similarity index 97% rename from oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectWebFilterTests.java rename to oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilterTests.java index b2ff790cbe..c6e0f51b6c 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectWebFilterTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilterTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.security.oauth2.client.web; +package org.springframework.security.oauth2.client.web.server; import org.junit.Before; import org.junit.Test; @@ -52,7 +52,7 @@ public class OAuth2AuthorizationRequestRedirectWebFilterTests { private ReactiveClientRegistrationRepository clientRepository; @Mock - private ReactiveAuthorizationRequestRepository authzRequestRepository; + private ServerAuthorizationRequestRepository authzRequestRepository; private ClientRegistration github = ClientRegistration.withRegistrationId("github") .redirectUriTemplate("{baseUrl}/{action}/oauth2/code/{registrationId}") diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/ServerOAuth2LoginAuthenticationTokenConverterTest.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2LoginAuthenticationTokenConverterTest.java similarity index 97% rename from oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/ServerOAuth2LoginAuthenticationTokenConverterTest.java rename to oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2LoginAuthenticationTokenConverterTest.java index 793cc45f8c..e65530f224 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/ServerOAuth2LoginAuthenticationTokenConverterTest.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/ServerOAuth2LoginAuthenticationTokenConverterTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.security.oauth2.client.web; +package org.springframework.security.oauth2.client.web.server; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -52,7 +52,7 @@ public class ServerOAuth2LoginAuthenticationTokenConverterTest { private ReactiveClientRegistrationRepository clientRegistrationRepository; @Mock - private ReactiveAuthorizationRequestRepository authorizationRequestRepository; + private ServerAuthorizationRequestRepository authorizationRequestRepository; private String clientRegistrationId = "github"; diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/WebSessionOAuth2ReactiveAuthorizationRequestRepositoryTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepositoryTests.java similarity index 97% rename from oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/WebSessionOAuth2ReactiveAuthorizationRequestRepositoryTests.java rename to oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepositoryTests.java index 142fc0a8da..5fe05b69ea 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/WebSessionOAuth2ReactiveAuthorizationRequestRepositoryTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/WebSessionOAuth2ServerAuthorizationRequestRepositoryTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.security.oauth2.client.web; +package org.springframework.security.oauth2.client.web.server; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -40,10 +40,10 @@ import reactor.test.StepVerifier; * @author Rob Winch * @since 5.1 */ -public class WebSessionOAuth2ReactiveAuthorizationRequestRepositoryTests { +public class WebSessionOAuth2ServerAuthorizationRequestRepositoryTests { - private WebSessionOAuth2ReactiveAuthorizationRequestRepository repository = - new WebSessionOAuth2ReactiveAuthorizationRequestRepository(); + private WebSessionOAuth2ServerAuthorizationRequestRepository repository = + new WebSessionOAuth2ServerAuthorizationRequestRepository(); private OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() .authorizationUri("https://example.com/oauth2/authorize")