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 <mail@andreaskluth.net>
This commit is contained in:
parent
26a65249f9
commit
c46b224ec4
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -85,6 +85,9 @@ public final class WebSessionOAuth2ServerAuthorizationRequestRepository
|
||||||
OAuth2AuthorizationRequest removedValue = stateToAuthzRequest.remove(state);
|
OAuth2AuthorizationRequest removedValue = stateToAuthzRequest.remove(state);
|
||||||
if (stateToAuthzRequest.isEmpty()) {
|
if (stateToAuthzRequest.isEmpty()) {
|
||||||
sessionAttrs.remove(this.sessionAttributeName);
|
sessionAttrs.remove(this.sessionAttributeName);
|
||||||
|
} else if (removedValue != null) {
|
||||||
|
// gh-7327 Overwrite the existing Map to ensure the state is saved for distributed sessions
|
||||||
|
sessionAttrs.put(this.sessionAttributeName, stateToAuthzRequest);
|
||||||
}
|
}
|
||||||
if (removedValue == null) {
|
if (removedValue == null) {
|
||||||
sink.complete();
|
sink.complete();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -63,7 +63,7 @@ public class WebSessionOAuth2ServerAuthorizationRequestRepositoryTests {
|
||||||
.queryParam(OAuth2ParameterNames.STATE, "state"));
|
.queryParam(OAuth2ParameterNames.STATE, "state"));
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void loadAuthorizatioNRequestWhenNullExchangeThenIllegalArgumentException() {
|
public void loadAuthorizationRequestWhenNullExchangeThenIllegalArgumentException() {
|
||||||
this.exchange = null;
|
this.exchange = null;
|
||||||
assertThatThrownBy(() -> this.repository.loadAuthorizationRequest(this.exchange))
|
assertThatThrownBy(() -> this.repository.loadAuthorizationRequest(this.exchange))
|
||||||
.isInstanceOf(IllegalArgumentException.class);
|
.isInstanceOf(IllegalArgumentException.class);
|
||||||
|
@ -106,36 +106,6 @@ public class WebSessionOAuth2ServerAuthorizationRequestRepositoryTests {
|
||||||
.verifyComplete();
|
.verifyComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void multipleSavedAuthorizationRequestAndRedisCookie() {
|
|
||||||
String oldState = "state0";
|
|
||||||
MockServerHttpRequest oldRequest = MockServerHttpRequest.get("/")
|
|
||||||
.queryParam(OAuth2ParameterNames.STATE, oldState).build();
|
|
||||||
|
|
||||||
OAuth2AuthorizationRequest oldAuthorizationRequest = OAuth2AuthorizationRequest.authorizationCode()
|
|
||||||
.authorizationUri("https://example.com/oauth2/authorize")
|
|
||||||
.clientId("client-id")
|
|
||||||
.redirectUri("http://localhost/client-1")
|
|
||||||
.state(oldState)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
Map<String, Object> sessionAttrs = spy(new HashMap<>());
|
|
||||||
WebSession session = mock(WebSession.class);
|
|
||||||
when(session.getAttributes()).thenReturn(sessionAttrs);
|
|
||||||
WebSessionManager sessionManager = e -> Mono.just(session);
|
|
||||||
|
|
||||||
this.exchange = new DefaultServerWebExchange(this.exchange.getRequest(), new MockServerHttpResponse(), sessionManager,
|
|
||||||
ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver());
|
|
||||||
ServerWebExchange oldExchange = new DefaultServerWebExchange(oldRequest, new MockServerHttpResponse(), sessionManager,
|
|
||||||
ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver());
|
|
||||||
|
|
||||||
Mono<Void> saveAndSave = this.repository.saveAuthorizationRequest(oldAuthorizationRequest, oldExchange)
|
|
||||||
.then(this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange));
|
|
||||||
|
|
||||||
StepVerifier.create(saveAndSave).verifyComplete();
|
|
||||||
verify(sessionAttrs, times(2)).put(any(), any());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void loadAuthorizationRequestWhenMultipleSavedThenAuthorizationRequest() {
|
public void loadAuthorizationRequestWhenMultipleSavedThenAuthorizationRequest() {
|
||||||
String oldState = "state0";
|
String oldState = "state0";
|
||||||
|
@ -269,6 +239,44 @@ public class WebSessionOAuth2ServerAuthorizationRequestRepositoryTests {
|
||||||
.verifyComplete();
|
.verifyComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gh-7327
|
||||||
|
@Test
|
||||||
|
public void removeAuthorizationRequestWhenMultipleThenRemovedAndSessionAttributeUpdated() {
|
||||||
|
String oldState = "state0";
|
||||||
|
MockServerHttpRequest oldRequest = MockServerHttpRequest.get("/")
|
||||||
|
.queryParam(OAuth2ParameterNames.STATE, oldState).build();
|
||||||
|
|
||||||
|
OAuth2AuthorizationRequest oldAuthorizationRequest = OAuth2AuthorizationRequest.authorizationCode()
|
||||||
|
.authorizationUri("https://example.com/oauth2/authorize")
|
||||||
|
.clientId("client-id")
|
||||||
|
.redirectUri("http://localhost/client-1")
|
||||||
|
.state(oldState)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Map<String, Object> sessionAttrs = spy(new HashMap<>());
|
||||||
|
WebSession session = mock(WebSession.class);
|
||||||
|
when(session.getAttributes()).thenReturn(sessionAttrs);
|
||||||
|
WebSessionManager sessionManager = e -> Mono.just(session);
|
||||||
|
|
||||||
|
this.exchange = new DefaultServerWebExchange(this.exchange.getRequest(), new MockServerHttpResponse(), sessionManager,
|
||||||
|
ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver());
|
||||||
|
ServerWebExchange oldExchange = new DefaultServerWebExchange(oldRequest, new MockServerHttpResponse(), sessionManager,
|
||||||
|
ServerCodecConfigurer.create(), new AcceptHeaderLocaleContextResolver());
|
||||||
|
|
||||||
|
Mono<OAuth2AuthorizationRequest> saveAndSaveAndRemove = this.repository.saveAuthorizationRequest(oldAuthorizationRequest, oldExchange)
|
||||||
|
.then(this.repository.saveAuthorizationRequest(this.authorizationRequest, this.exchange))
|
||||||
|
.then(this.repository.removeAuthorizationRequest(this.exchange));
|
||||||
|
|
||||||
|
StepVerifier.create(saveAndSaveAndRemove)
|
||||||
|
.expectNext(this.authorizationRequest)
|
||||||
|
.verifyComplete();
|
||||||
|
|
||||||
|
StepVerifier.create(this.repository.loadAuthorizationRequest(this.exchange))
|
||||||
|
.verifyComplete();
|
||||||
|
|
||||||
|
verify(sessionAttrs, times(3)).put(any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
private void assertSessionStartedIs(boolean expected) {
|
private void assertSessionStartedIs(boolean expected) {
|
||||||
Mono<Boolean> isStarted = this.exchange.getSession().map(WebSession::isStarted);
|
Mono<Boolean> isStarted = this.exchange.getSession().map(WebSession::isStarted);
|
||||||
StepVerifier.create(isStarted)
|
StepVerifier.create(isStarted)
|
||||||
|
|
Loading…
Reference in New Issue