Skip to content

Commit 57f3c76

Browse files
AndreasKljgrandja
authored andcommitted
Remove OAuth2AuthorizationRequest when a distributed session is used
Dirties the WebSession by putting the amended AUTHORIZATION_REQUEST map into the WebSession even it was already in the map. This causes common SessionRepository implementations like Redis to persist the updated attribute. Fixes gh-7327 Author: Andreas Kluth <[email protected]>
1 parent f8f1e9a commit 57f3c76

File tree

2 files changed

+44
-33
lines changed

2 files changed

+44
-33
lines changed

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

Lines changed: 4 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.
@@ -85,6 +85,9 @@ public Mono<OAuth2AuthorizationRequest> removeAuthorizationRequest(
8585
OAuth2AuthorizationRequest removedValue = stateToAuthzRequest.remove(state);
8686
if (stateToAuthzRequest.isEmpty()) {
8787
sessionAttrs.remove(this.sessionAttributeName);
88+
} else if (removedValue != null) {
89+
// gh-7327 Overwrite the existing Map to ensure the state is saved for distributed sessions
90+
sessionAttrs.put(this.sessionAttributeName, stateToAuthzRequest);
8891
}
8992
if (removedValue == null) {
9093
sink.complete();

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

Lines changed: 40 additions & 32 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.
@@ -63,7 +63,7 @@ public class WebSessionOAuth2ServerAuthorizationRequestRepositoryTests {
6363
.queryParam(OAuth2ParameterNames.STATE, "state"));
6464

6565
@Test
66-
public void loadAuthorizatioNRequestWhenNullExchangeThenIllegalArgumentException() {
66+
public void loadAuthorizationRequestWhenNullExchangeThenIllegalArgumentException() {
6767
this.exchange = null;
6868
assertThatThrownBy(() -> this.repository.loadAuthorizationRequest(this.exchange))
6969
.isInstanceOf(IllegalArgumentException.class);
@@ -106,36 +106,6 @@ public void loadAuthorizationRequestWhenSavedThenAuthorizationRequest() {
106106
.verifyComplete();
107107
}
108108

109-
@Test
110-
public void multipleSavedAuthorizationRequestAndRedisCookie() {
111-
String oldState = "state0";
112-
MockServerHttpRequest oldRequest = MockServerHttpRequest.get("/")
113-
.queryParam(OAuth2ParameterNames.STATE, oldState).build();
114-
115-
OAuth2AuthorizationRequest oldAuthorizationRequest = OAuth2AuthorizationRequest.authorizationCode()
116-
.authorizationUri("https://example.com/oauth2/authorize")
117-
.clientId("client-id")
118-
.redirectUri("http://localhost/client-1")
119-
.state(oldState)
120-
.build();
121-
122-
Map<String, Object> sessionAttrs = spy(new HashMap<>());
123-
WebSession session = mock(WebSession.class);
124-
when(session.getAttributes()).thenReturn(sessionAttrs);
125-
WebSessionManager sessionManager = e -> Mono.just(session);
126-
127-
this.exchange = new DefaultServerWebExchange(this.exchange.getRequest(), new MockServerHttpResponse(), sessionManager,
128-
ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver());
129-
ServerWebExchange oldExchange = new DefaultServerWebExchange(oldRequest, new MockServerHttpResponse(), sessionManager,
130-
ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver());
131-
132-
Mono<Void> saveAndSave = this.repository.saveAuthorizationRequest(oldAuthorizationRequest, oldExchange)
133-
.then(this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange));
134-
135-
StepVerifier.create(saveAndSave).verifyComplete();
136-
verify(sessionAttrs, times(2)).put(any(), any());
137-
}
138-
139109
@Test
140110
public void loadAuthorizationRequestWhenMultipleSavedThenAuthorizationRequest() {
141111
String oldState = "state0";
@@ -269,6 +239,44 @@ public void removeAuthorizationRequestWhenMultipleThenOnlyOneRemoved() {
269239
.verifyComplete();
270240
}
271241

242+
// gh-7327
243+
@Test
244+
public void removeAuthorizationRequestWhenMultipleThenRemovedAndSessionAttributeUpdated() {
245+
String oldState = "state0";
246+
MockServerHttpRequest oldRequest = MockServerHttpRequest.get("/")
247+
.queryParam(OAuth2ParameterNames.STATE, oldState).build();
248+
249+
OAuth2AuthorizationRequest oldAuthorizationRequest = OAuth2AuthorizationRequest.authorizationCode()
250+
.authorizationUri("https://example.com/oauth2/authorize")
251+
.clientId("client-id")
252+
.redirectUri("http://localhost/client-1")
253+
.state(oldState)
254+
.build();
255+
256+
Map<String, Object> sessionAttrs = spy(new HashMap<>());
257+
WebSession session = mock(WebSession.class);
258+
when(session.getAttributes()).thenReturn(sessionAttrs);
259+
WebSessionManager sessionManager = e -> Mono.just(session);
260+
261+
this.exchange = new DefaultServerWebExchange(this.exchange.getRequest(), new MockServerHttpResponse(), sessionManager,
262+
ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver());
263+
ServerWebExchange oldExchange = new DefaultServerWebExchange(oldRequest, new MockServerHttpResponse(), sessionManager,
264+
ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver());
265+
266+
Mono<OAuth2AuthorizationRequest> saveAndSaveAndRemove = this.repository.saveAuthorizationRequest(oldAuthorizationRequest, oldExchange)
267+
.then(this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange))
268+
.then(this.repository.removeAuthorizationRequest(this.exchange));
269+
270+
StepVerifier.create(saveAndSaveAndRemove)
271+
.expectNext(this.authorizationRequest)
272+
.verifyComplete();
273+
274+
StepVerifier.create(this.repository.loadAuthorizationRequest(this.exchange))
275+
.verifyComplete();
276+
277+
verify(sessionAttrs, times(3)).put(any(), any());
278+
}
279+
272280
private void assertSessionStartedIs(boolean expected) {
273281
Mono<Boolean> isStarted = this.exchange.getSession().map(WebSession::isStarted);
274282
StepVerifier.create(isStarted)

0 commit comments

Comments
 (0)