Consistent .server package for ServerWebExchange OAuth2

Fixes: gh-5663
This commit is contained in:
Rob Winch 2018-08-17 21:44:37 -05:00
parent cbd28cfd1e
commit 5ddb25fff8
9 changed files with 120 additions and 27 deletions

View File

@ -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;

View File

@ -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<OAuth2AuthorizationRequest> authorizationRequestRepository =
new WebSessionOAuth2ReactiveAuthorizationRequestRepository();
private ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> 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<OAuth2AuthorizationRequest> authorizationRequestRepository) {
public final void setAuthorizationRequestRepository(
ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository) {
Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null");
this.authorizationRequestRepository = authorizationRequestRepository;
}

View File

@ -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<String, String> toMultiMap(Map<String, String[]> map) {
MultiValueMap<String, String> 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<String, String> request) {
return isAuthorizationResponseSuccess(request) || isAuthorizationResponseError(request);
}
static boolean isAuthorizationResponseSuccess(MultiValueMap<String, String> request) {
return StringUtils.hasText(request.getFirst(OAuth2ParameterNames.CODE)) &&
StringUtils.hasText(request.getFirst(OAuth2ParameterNames.STATE));
}
static boolean isAuthorizationResponseError(MultiValueMap<String, String> request) {
return StringUtils.hasText(request.getFirst(OAuth2ParameterNames.ERROR)) &&
StringUtils.hasText(request.getFirst(OAuth2ParameterNames.STATE));
}
static OAuth2AuthorizationResponse convert(MultiValueMap<String, String> 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();
}
}
}

View File

@ -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 <T> The type of OAuth 2.0 Authorization Request
*/
public interface ReactiveAuthorizationRequestRepository<T extends OAuth2AuthorizationRequest> {
public interface ServerAuthorizationRequestRepository<T extends OAuth2AuthorizationRequest> {
/**
* Returns the {@link OAuth2AuthorizationRequest} associated to the provided {@code HttpServletRequest}

View File

@ -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<OAuth2AuthorizationRequest> authorizationRequestRepository =
new WebSessionOAuth2ReactiveAuthorizationRequestRepository();
private ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> 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<OAuth2AuthorizationRequest> authorizationRequestRepository) {
ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> 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);
}
}

View File

@ -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<OAuth2AuthorizationRequest> {
public final class WebSessionOAuth2ServerAuthorizationRequestRepository
implements ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> {
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;

View File

@ -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<OAuth2AuthorizationRequest> authzRequestRepository;
private ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> authzRequestRepository;
private ClientRegistration github = ClientRegistration.withRegistrationId("github")
.redirectUriTemplate("{baseUrl}/{action}/oauth2/code/{registrationId}")

View File

@ -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";

View File

@ -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")