mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-02-21 05:44:56 +00:00
Add ServerOAuth2AuthorizationRequestResolver
Fixes: gh-5610
This commit is contained in:
parent
b9ab4929b7
commit
85d5d4083f
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
|
||||
import org.springframework.security.crypto.keygen.Base64StringKeyGenerator;
|
||||
import org.springframework.security.crypto.keygen.StringKeyGenerator;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.web.server.util.matcher.PathPatternParserServerWebExchangeMatcher;
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The default implementation of {@link ServerOAuth2AuthorizationRequestResolver}.
|
||||
*
|
||||
* The {@link ClientRegistration#getRegistrationId()} is extracted from the request using the
|
||||
* {@link #DEFAULT_AUTHORIZATION_REQUEST_PATTERN}. The injected {@link ReactiveClientRegistrationRepository} is then
|
||||
* used to resolve the {@link ClientRegistration} and create the {@link OAuth2AuthorizationRequest}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.1
|
||||
*/
|
||||
public class DefaultServerOAuth2AuthorizationRequestResolver
|
||||
implements ServerOAuth2AuthorizationRequestResolver {
|
||||
|
||||
/**
|
||||
* The name of the path variable that contains the {@link ClientRegistration#getRegistrationId()}
|
||||
*/
|
||||
public static final String DEFAULT_REGISTRATION_ID_URI_VARIABLE_NAME = "registrationId";
|
||||
|
||||
/**
|
||||
* The default pattern used to resolve the {@link ClientRegistration#getRegistrationId()}
|
||||
*/
|
||||
public static final String DEFAULT_AUTHORIZATION_REQUEST_PATTERN = "/oauth2/authorization/{" + DEFAULT_REGISTRATION_ID_URI_VARIABLE_NAME
|
||||
+ "}";
|
||||
|
||||
private final ServerWebExchangeMatcher authorizationRequestMatcher;
|
||||
|
||||
private final ReactiveClientRegistrationRepository clientRegistrationRepository;
|
||||
|
||||
private final StringKeyGenerator stateGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder());
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param clientRegistrationRepository the repository to resolve the {@link ClientRegistration}
|
||||
*/
|
||||
public DefaultServerOAuth2AuthorizationRequestResolver(ReactiveClientRegistrationRepository clientRegistrationRepository) {
|
||||
this(clientRegistrationRepository, new PathPatternParserServerWebExchangeMatcher(
|
||||
DEFAULT_AUTHORIZATION_REQUEST_PATTERN));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param clientRegistrationRepository the repository to resolve the {@link ClientRegistration}
|
||||
* @param authorizationRequestMatcher the matcher that determines if the request is a match and extracts the
|
||||
* {@link #DEFAULT_REGISTRATION_ID_URI_VARIABLE_NAME} from the path variables.
|
||||
*/
|
||||
public DefaultServerOAuth2AuthorizationRequestResolver(ReactiveClientRegistrationRepository clientRegistrationRepository,
|
||||
ServerWebExchangeMatcher authorizationRequestMatcher) {
|
||||
Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
|
||||
Assert.notNull(authorizationRequestMatcher, "authorizationRequestMatcher cannot be null");
|
||||
this.clientRegistrationRepository = clientRegistrationRepository;
|
||||
this.authorizationRequestMatcher = authorizationRequestMatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<OAuth2AuthorizationRequest> resolve(ServerWebExchange exchange) {
|
||||
return this.authorizationRequestMatcher.matches(exchange)
|
||||
.filter(matchResult -> matchResult.isMatch())
|
||||
.map(ServerWebExchangeMatcher.MatchResult::getVariables)
|
||||
.map(variables -> variables.get(DEFAULT_REGISTRATION_ID_URI_VARIABLE_NAME))
|
||||
.cast(String.class)
|
||||
.flatMap(clientRegistrationId -> resolve(exchange, clientRegistrationId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<OAuth2AuthorizationRequest> resolve(ServerWebExchange exchange,
|
||||
String clientRegistrationId) {
|
||||
return this.findByRegistrationId(exchange, clientRegistrationId)
|
||||
.map(clientRegistration -> authorizationRequest(exchange, clientRegistration));
|
||||
}
|
||||
|
||||
private Mono<ClientRegistration> findByRegistrationId(ServerWebExchange exchange, String clientRegistration) {
|
||||
return this.clientRegistrationRepository.findByRegistrationId(clientRegistration)
|
||||
.switchIfEmpty(Mono.error(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid client registration id")));
|
||||
}
|
||||
|
||||
private OAuth2AuthorizationRequest authorizationRequest(ServerWebExchange exchange,
|
||||
ClientRegistration clientRegistration) {
|
||||
String redirectUriStr = this
|
||||
.expandRedirectUri(exchange.getRequest(), clientRegistration);
|
||||
|
||||
Map<String, Object> additionalParameters = new HashMap<>();
|
||||
additionalParameters.put(OAuth2ParameterNames.REGISTRATION_ID,
|
||||
clientRegistration.getRegistrationId());
|
||||
|
||||
OAuth2AuthorizationRequest.Builder builder;
|
||||
if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())) {
|
||||
builder = OAuth2AuthorizationRequest.authorizationCode();
|
||||
}
|
||||
else if (AuthorizationGrantType.IMPLICIT.equals(clientRegistration.getAuthorizationGrantType())) {
|
||||
builder = OAuth2AuthorizationRequest.implicit();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid Authorization Grant Type (" + clientRegistration.getAuthorizationGrantType().getValue()
|
||||
+ ") for Client Registration with Id: " + clientRegistration.getRegistrationId());
|
||||
}
|
||||
return builder
|
||||
.clientId(clientRegistration.getClientId())
|
||||
.authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri())
|
||||
.redirectUri(redirectUriStr).scopes(clientRegistration.getScopes())
|
||||
.state(this.stateGenerator.generateKey())
|
||||
.additionalParameters(additionalParameters)
|
||||
.build();
|
||||
}
|
||||
|
||||
private String expandRedirectUri(ServerHttpRequest request, ClientRegistration clientRegistration) {
|
||||
// Supported URI variables -> baseUrl, action, registrationId
|
||||
// Used in -> CommonOAuth2Provider.DEFAULT_REDIRECT_URL = "{baseUrl}/{action}/oauth2/code/{registrationId}"
|
||||
Map<String, String> uriVariables = new HashMap<>();
|
||||
uriVariables.put("registrationId", clientRegistration.getRegistrationId());
|
||||
|
||||
String baseUrl = UriComponentsBuilder.fromHttpRequest(new ServerHttpRequestDecorator(request))
|
||||
.replacePath(request.getPath().contextPath().value())
|
||||
.replaceQuery(null)
|
||||
.build()
|
||||
.toUriString();
|
||||
uriVariables.put("baseUrl", baseUrl);
|
||||
|
||||
if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())) {
|
||||
String loginAction = "login";
|
||||
uriVariables.put("action", loginAction);
|
||||
}
|
||||
|
||||
return UriComponentsBuilder.fromUriString(clientRegistration.getRedirectUriTemplate())
|
||||
.buildAndExpand(uriVariables)
|
||||
.toUriString();
|
||||
}
|
||||
}
|
@ -15,16 +15,6 @@
|
||||
*/
|
||||
package org.springframework.security.oauth2.client.web.server;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
|
||||
import org.springframework.security.crypto.keygen.Base64StringKeyGenerator;
|
||||
import org.springframework.security.crypto.keygen.StringKeyGenerator;
|
||||
import org.springframework.security.oauth2.client.ClientAuthorizationRequiredException;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||
@ -32,19 +22,17 @@ import org.springframework.security.oauth2.client.registration.ReactiveClientReg
|
||||
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;
|
||||
import org.springframework.security.web.server.DefaultServerRedirectStrategy;
|
||||
import org.springframework.security.web.server.ServerRedirectStrategy;
|
||||
import org.springframework.security.web.server.util.matcher.PathPatternParserServerWebExchangeMatcher;
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* This {@code WebFilter} initiates the authorization code grant or implicit grant flow
|
||||
* by redirecting the End-User's user-agent to the Authorization Server's Authorization Endpoint.
|
||||
@ -63,10 +51,6 @@ import reactor.core.publisher.Mono;
|
||||
* {@link ClientRegistration#getRegistrationId() registration identifier} of the client
|
||||
* that is used for initiating the OAuth 2.0 Authorization Request.
|
||||
*
|
||||
* <p>
|
||||
* <b>NOTE:</b> The default base {@code URI} {@code /oauth2/authorization} may be overridden
|
||||
* via it's constructor {@link #OAuth2AuthorizationRequestRedirectWebFilter(ReactiveClientRegistrationRepository, String)}.
|
||||
|
||||
* @author Rob Winch
|
||||
* @since 5.1
|
||||
* @see OAuth2AuthorizationRequest
|
||||
@ -79,17 +63,8 @@ import reactor.core.publisher.Mono;
|
||||
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.2.1">Section 4.2.1 Authorization Request (Implicit)</a>
|
||||
*/
|
||||
public class OAuth2AuthorizationRequestRedirectWebFilter implements WebFilter {
|
||||
/**
|
||||
* The default base {@code URI} used for authorization requests.
|
||||
*/
|
||||
public static final String DEFAULT_AUTHORIZATION_REQUEST_BASE_URI = "/oauth2/authorization";
|
||||
private static final String REGISTRATION_ID_URI_VARIABLE_NAME = "registrationId";
|
||||
private static final String AUTHORIZATION_REQUIRED_EXCEPTION_ATTR_NAME =
|
||||
ClientAuthorizationRequiredException.class.getName() + ".AUTHORIZATION_REQUIRED_EXCEPTION";
|
||||
private final ServerWebExchangeMatcher authorizationRequestMatcher;
|
||||
private final ReactiveClientRegistrationRepository clientRegistrationRepository;
|
||||
private final ServerRedirectStrategy authorizationRedirectStrategy = new DefaultServerRedirectStrategy();
|
||||
private final StringKeyGenerator stateGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder());
|
||||
private final ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver;
|
||||
private ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository =
|
||||
new WebSessionOAuth2ServerAuthorizationRequestRepository();
|
||||
|
||||
@ -99,23 +74,17 @@ public class OAuth2AuthorizationRequestRedirectWebFilter implements WebFilter {
|
||||
* @param clientRegistrationRepository the repository of client registrations
|
||||
*/
|
||||
public OAuth2AuthorizationRequestRedirectWebFilter(ReactiveClientRegistrationRepository clientRegistrationRepository) {
|
||||
this(clientRegistrationRepository, DEFAULT_AUTHORIZATION_REQUEST_BASE_URI);
|
||||
this.authorizationRequestResolver = new DefaultServerOAuth2AuthorizationRequestResolver(clientRegistrationRepository);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an {@code OAuth2AuthorizationRequestRedirectFilter} using the provided parameters.
|
||||
*
|
||||
* @param clientRegistrationRepository the repository of client registrations
|
||||
* @param authorizationRequestBaseUri the base {@code URI} used for authorization requests
|
||||
* @param authorizationRequestResolver the resolver to use
|
||||
*/
|
||||
public OAuth2AuthorizationRequestRedirectWebFilter(
|
||||
ReactiveClientRegistrationRepository clientRegistrationRepository, String authorizationRequestBaseUri) {
|
||||
|
||||
Assert.hasText(authorizationRequestBaseUri, "authorizationRequestBaseUri cannot be empty");
|
||||
Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
|
||||
this.authorizationRequestMatcher = new PathPatternParserServerWebExchangeMatcher(
|
||||
authorizationRequestBaseUri + "/{" + REGISTRATION_ID_URI_VARIABLE_NAME + "}");
|
||||
this.clientRegistrationRepository = clientRegistrationRepository;
|
||||
public OAuth2AuthorizationRequestRedirectWebFilter(ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver) {
|
||||
Assert.notNull(authorizationRequestResolver, "authorizationRequestResolver cannot be null");
|
||||
this.authorizationRequestResolver = authorizationRequestResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,54 +100,15 @@ public class OAuth2AuthorizationRequestRedirectWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
return this.authorizationRequestMatcher.matches(exchange)
|
||||
.filter(matchResult -> matchResult.isMatch())
|
||||
return this.authorizationRequestResolver.resolve(exchange)
|
||||
.switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
|
||||
.map(ServerWebExchangeMatcher.MatchResult::getVariables)
|
||||
.map(variables -> variables.get(REGISTRATION_ID_URI_VARIABLE_NAME))
|
||||
.cast(String.class)
|
||||
.onErrorResume(ClientAuthorizationRequiredException.class, e -> Mono.just(e.getClientRegistrationId()))
|
||||
.flatMap(clientRegistrationId -> this.findByRegistrationId(exchange, clientRegistrationId))
|
||||
.onErrorResume(ClientAuthorizationRequiredException.class, e -> this.authorizationRequestResolver.resolve(exchange, e.getClientRegistrationId()))
|
||||
.flatMap(clientRegistration -> sendRedirectForAuthorization(exchange, clientRegistration));
|
||||
}
|
||||
|
||||
private Mono<ClientRegistration> findByRegistrationId(ServerWebExchange exchange, String clientRegistration) {
|
||||
return this.clientRegistrationRepository.findByRegistrationId(clientRegistration)
|
||||
.switchIfEmpty(Mono.defer(() -> {
|
||||
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
|
||||
return exchange.getResponse().setComplete().then(Mono.empty());
|
||||
}));
|
||||
}
|
||||
|
||||
private Mono<Void> sendRedirectForAuthorization(ServerWebExchange exchange,
|
||||
ClientRegistration clientRegistration) {
|
||||
OAuth2AuthorizationRequest authorizationRequest) {
|
||||
return Mono.defer(() -> {
|
||||
String redirectUriStr = this
|
||||
.expandRedirectUri(exchange.getRequest(), clientRegistration);
|
||||
|
||||
Map<String, Object> additionalParameters = new HashMap<>();
|
||||
additionalParameters.put(OAuth2ParameterNames.REGISTRATION_ID,
|
||||
clientRegistration.getRegistrationId());
|
||||
|
||||
OAuth2AuthorizationRequest.Builder builder;
|
||||
if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())) {
|
||||
builder = OAuth2AuthorizationRequest.authorizationCode();
|
||||
}
|
||||
else if (AuthorizationGrantType.IMPLICIT.equals(clientRegistration.getAuthorizationGrantType())) {
|
||||
builder = OAuth2AuthorizationRequest.implicit();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid Authorization Grant Type (" + clientRegistration.getAuthorizationGrantType().getValue()
|
||||
+ ") for Client Registration with Id: " + clientRegistration.getRegistrationId());
|
||||
}
|
||||
OAuth2AuthorizationRequest authorizationRequest = builder
|
||||
.clientId(clientRegistration.getClientId())
|
||||
.authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri())
|
||||
.redirectUri(redirectUriStr).scopes(clientRegistration.getScopes())
|
||||
.state(this.stateGenerator.generateKey())
|
||||
.additionalParameters(additionalParameters).build();
|
||||
|
||||
Mono<Void> saveAuthorizationRequest = Mono.empty();
|
||||
if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(authorizationRequest.getGrantType())) {
|
||||
saveAuthorizationRequest = this.authorizationRequestRepository
|
||||
@ -192,27 +122,4 @@ public class OAuth2AuthorizationRequestRedirectWebFilter implements WebFilter {
|
||||
.then(this.authorizationRedirectStrategy.sendRedirect(exchange, redirectUri));
|
||||
});
|
||||
}
|
||||
|
||||
private String expandRedirectUri(ServerHttpRequest request, ClientRegistration clientRegistration) {
|
||||
// Supported URI variables -> baseUrl, action, registrationId
|
||||
// Used in -> CommonOAuth2Provider.DEFAULT_REDIRECT_URL = "{baseUrl}/{action}/oauth2/code/{registrationId}"
|
||||
Map<String, String> uriVariables = new HashMap<>();
|
||||
uriVariables.put("registrationId", clientRegistration.getRegistrationId());
|
||||
|
||||
String baseUrl = UriComponentsBuilder.fromHttpRequest(new ServerHttpRequestDecorator(request))
|
||||
.replacePath(request.getPath().contextPath().value())
|
||||
.replaceQuery(null)
|
||||
.build()
|
||||
.toUriString();
|
||||
uriVariables.put("baseUrl", baseUrl);
|
||||
|
||||
if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())) {
|
||||
String loginAction = "login";
|
||||
uriVariables.put("action", loginAction);
|
||||
}
|
||||
|
||||
return UriComponentsBuilder.fromUriString(clientRegistration.getRedirectUriTemplate())
|
||||
.buildAndExpand(uriVariables)
|
||||
.toUriString();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.OAuth2AuthorizationRequest;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Implementations of this interface are capable of resolving
|
||||
* an {@link OAuth2AuthorizationRequest} from the provided {@code ServerWebExchange}.
|
||||
* Used by the {@link OAuth2AuthorizationRequestRedirectWebFilter} for resolving Authorization Requests.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.1
|
||||
* @see OAuth2AuthorizationRequest
|
||||
* @see OAuth2AuthorizationRequestRedirectWebFilter
|
||||
*/
|
||||
public interface ServerOAuth2AuthorizationRequestResolver {
|
||||
|
||||
/**
|
||||
* Returns the {@link OAuth2AuthorizationRequest} resolved from
|
||||
* the provided {@code HttpServletRequest} or {@code null} if not available.
|
||||
*
|
||||
* @param exchange the {@code ServerWebExchange}
|
||||
* @return the resolved {@link OAuth2AuthorizationRequest} or {@code null} if not available
|
||||
*/
|
||||
Mono<OAuth2AuthorizationRequest> resolve(ServerWebExchange exchange);
|
||||
|
||||
/**
|
||||
* Returns the {@link OAuth2AuthorizationRequest} resolved from
|
||||
* the provided {@code HttpServletRequest} or {@code null} if not available.
|
||||
*
|
||||
* @param exchange the {@code ServerWebExchange}
|
||||
* @param clientRegistrationId the client registration id
|
||||
* @return the resolved {@link OAuth2AuthorizationRequest} or {@code null} if not available
|
||||
*/
|
||||
Mono<OAuth2AuthorizationRequest> resolve(ServerWebExchange exchange, String clientRegistrationId);
|
||||
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.mock.web.server.MockServerWebExchange;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
|
||||
import org.springframework.security.oauth2.client.registration.TestClientRegistrations;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.catchThrowableOfType;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.1
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DefaultServerOAuth2AuthorizationRequestResolverTests {
|
||||
@Mock
|
||||
private ReactiveClientRegistrationRepository clientRegistrationRepository;
|
||||
|
||||
private DefaultServerOAuth2AuthorizationRequestResolver resolver;
|
||||
|
||||
private ClientRegistration registration = TestClientRegistrations.clientRegistration().build();
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.resolver = new DefaultServerOAuth2AuthorizationRequestResolver(this.clientRegistrationRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveWhenNotMatchThenNull() {
|
||||
assertThat(resolve("/")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveWhenClientRegistrationNotFoundMatchThenBadRequest() {
|
||||
when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(
|
||||
Mono.empty());
|
||||
|
||||
ResponseStatusException expected = catchThrowableOfType(() -> resolve("/oauth2/authorization/not-found-id"), ResponseStatusException.class);
|
||||
|
||||
assertThat(expected.getStatus()).isEqualTo(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveWhenClientRegistrationFoundThenWorks() {
|
||||
when(this.clientRegistrationRepository.findByRegistrationId(any())).thenReturn(
|
||||
Mono.just(this.registration));
|
||||
|
||||
OAuth2AuthorizationRequest request = resolve("/oauth2/authorization/not-found-id");
|
||||
|
||||
assertThat(request.getAuthorizationRequestUri()).matches("https://example.com/login/oauth/authorize\\?response_type=code&client_id=client-id&scope=read%3Auser&state=.*?&redirect_uri=%2Flogin%2Foauth2%2Fcode%2Fregistration-id");
|
||||
}
|
||||
|
||||
private OAuth2AuthorizationRequest resolve(String path) {
|
||||
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get(path));
|
||||
return this.resolver.resolve(exchange).block();
|
||||
}
|
||||
}
|
@ -79,20 +79,6 @@ public class OAuth2AuthorizationRequestRedirectWebFilterTests {
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenAuthorizationRequestBaseUriNullThenIllegalArgumentException() {
|
||||
String authorizationRequestBaseUri = null;
|
||||
assertThatThrownBy(() -> new OAuth2AuthorizationRequestRedirectWebFilter(this.clientRepository, authorizationRequestBaseUri))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenAuthorizationRequestBaseUriEmptyThenIllegalArgumentException() {
|
||||
String authorizationRequestBaseUri = "";
|
||||
assertThatThrownBy(() -> new OAuth2AuthorizationRequestRedirectWebFilter(this.clientRepository, authorizationRequestBaseUri))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterWhenDoesNotMatchThenClientRegistrationRepositoryNotSubscribed() {
|
||||
this.client.get()
|
||||
|
Loading…
x
Reference in New Issue
Block a user