Skip to content

Commit 9ccbe21

Browse files
committed
Save original request on oauth2Client filter
When we used the oauth2Client directive and requested an endpoint that required client authorization on the authorization server, the SPRING_SECURITY_SAVED_REQUEST was not persisted, and therefore after creating the authorized client we were redirected to the root page ("/"). Now we are storing the session attribute and getting redirected back to the original URI as expected. Note that the attribute is stored only when a ClientAuthorizationRequiredException is thrown in the chain, we dont want to store it as a response to the /oauth2/authorization/{registrationId} endpoint, since we would end up in an infinite loop Fixes spring-projectsgh-6341
1 parent b7ed919 commit 9ccbe21

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilter.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,6 +24,8 @@
2424
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
2525
import org.springframework.security.web.server.DefaultServerRedirectStrategy;
2626
import org.springframework.security.web.server.ServerRedirectStrategy;
27+
import org.springframework.security.web.server.savedrequest.ServerRequestCache;
28+
import org.springframework.security.web.server.savedrequest.WebSessionServerRequestCache;
2729
import org.springframework.util.Assert;
2830
import org.springframework.web.server.ServerWebExchange;
2931
import org.springframework.web.server.WebFilter;
@@ -67,6 +69,7 @@ public class OAuth2AuthorizationRequestRedirectWebFilter implements WebFilter {
6769
private final ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver;
6870
private ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository =
6971
new WebSessionOAuth2ServerAuthorizationRequestRepository();
72+
private ServerRequestCache requestCache = new WebSessionServerRequestCache();
7073

7174
/**
7275
* Constructs an {@code OAuth2AuthorizationRequestRedirectFilter} using the provided parameters.
@@ -98,11 +101,23 @@ public final void setAuthorizationRequestRepository(
98101
this.authorizationRequestRepository = authorizationRequestRepository;
99102
}
100103

104+
/**
105+
* The request cache to use to save the request before sending a redirect.
106+
* @param requestCache the cache to redirect to.
107+
*/
108+
public void setRequestCache(ServerRequestCache requestCache) {
109+
Assert.notNull(requestCache, "requestCache cannot be null");
110+
this.requestCache = requestCache;
111+
}
112+
101113
@Override
102114
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
103115
return this.authorizationRequestResolver.resolve(exchange)
104116
.switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
105-
.onErrorResume(ClientAuthorizationRequiredException.class, e -> this.authorizationRequestResolver.resolve(exchange, e.getClientRegistrationId()))
117+
.onErrorResume(ClientAuthorizationRequiredException.class, e -> {
118+
return this.requestCache.saveRequest(exchange)
119+
.then(this.authorizationRequestResolver.resolve(exchange, e.getClientRegistrationId()));
120+
})
106121
.flatMap(clientRegistration -> sendRedirectForAuthorization(exchange, clientRegistration));
107122
}
108123

oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationRequestRedirectWebFilterTests.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
2626
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
2727
import org.springframework.security.oauth2.client.registration.TestClientRegistrations;
2828
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
29+
import org.springframework.security.web.server.savedrequest.ServerRequestCache;
2930
import org.springframework.test.web.reactive.server.FluxExchangeResult;
3031
import org.springframework.test.web.reactive.server.WebTestClient;
3132
import org.springframework.web.server.handler.FilteringWebHandler;
@@ -53,6 +54,9 @@ public class OAuth2AuthorizationRequestRedirectWebFilterTests {
5354
@Mock
5455
private ServerAuthorizationRequestRepository<OAuth2AuthorizationRequest> authzRequestRepository;
5556

57+
@Mock
58+
private ServerRequestCache requestCache;
59+
5660
private ClientRegistration registration = TestClientRegistrations.clientRegistration().build();
5761

5862
private OAuth2AuthorizationRequestRedirectWebFilter filter;
@@ -139,4 +143,33 @@ public void filterWhenExceptionThenRedirected() {
139143
.is3xxRedirection()
140144
.returnResult(String.class);
141145
}
146+
147+
@Test
148+
public void filterWhenExceptionThenSaveRequestSessionAttribute() {
149+
this.filter.setRequestCache(this.requestCache);
150+
when(this.requestCache.saveRequest(any())).thenReturn(Mono.empty());
151+
FilteringWebHandler webHandler = new FilteringWebHandler(
152+
e -> Mono.error(new ClientAuthorizationRequiredException(this.registration.getRegistrationId())),
153+
Arrays.asList(this.filter));
154+
this.client = WebTestClient.bindToWebHandler(webHandler).build();
155+
this.client.get()
156+
.uri("https://example.com/foo")
157+
.exchange()
158+
.expectStatus()
159+
.is3xxRedirection()
160+
.returnResult(String.class);
161+
verify(this.requestCache).saveRequest(any());
162+
}
163+
164+
@Test
165+
public void filterWhenPathMatchesThenRequestSessionAttributeNotSaved() {
166+
this.filter.setRequestCache(this.requestCache);
167+
this.client.get()
168+
.uri("https://example.com/oauth2/authorization/registration-id")
169+
.exchange()
170+
.expectStatus()
171+
.is3xxRedirection()
172+
.returnResult(String.class);
173+
verifyZeroInteractions(this.requestCache);
174+
}
142175
}

0 commit comments

Comments
 (0)