Skip to content

Commit 700bda6

Browse files
sjohnrSteve Riesenberg
authored andcommitted
Store one request by default in WebSessionOAuth2ServerAuthorizationRequestRepository
Related to gh-9649 Closes gh-9857
1 parent 53870ab commit 700bda6

File tree

4 files changed

+478
-171
lines changed

4 files changed

+478
-171
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2021 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.
@@ -34,6 +34,7 @@
3434
* {@link OAuth2AuthorizationRequest} in the {@code WebSession}.
3535
*
3636
* @author Rob Winch
37+
* @author Steve Riesenberg
3738
* @since 5.1
3839
* @see AuthorizationRequestRepository
3940
* @see OAuth2AuthorizationRequest
@@ -46,14 +47,18 @@ public final class WebSessionOAuth2ServerAuthorizationRequestRepository
4647

4748
private final String sessionAttributeName = DEFAULT_AUTHORIZATION_REQUEST_ATTR_NAME;
4849

50+
private boolean allowMultipleAuthorizationRequests;
51+
4952
@Override
5053
public Mono<OAuth2AuthorizationRequest> loadAuthorizationRequest(ServerWebExchange exchange) {
5154
String state = getStateParameter(exchange);
5255
if (state == null) {
5356
return Mono.empty();
5457
}
5558
// @formatter:off
56-
return getStateToAuthorizationRequest(exchange)
59+
return this.getSessionAttributes(exchange)
60+
.filter((sessionAttrs) -> sessionAttrs.containsKey(this.sessionAttributeName))
61+
.map(this::getAuthorizationRequests)
5762
.filter((stateToAuthorizationRequest) -> stateToAuthorizationRequest.containsKey(state))
5863
.map((stateToAuthorizationRequest) -> stateToAuthorizationRequest.get(state));
5964
// @formatter:on
@@ -63,10 +68,20 @@ public Mono<OAuth2AuthorizationRequest> loadAuthorizationRequest(ServerWebExchan
6368
public Mono<Void> saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest,
6469
ServerWebExchange exchange) {
6570
Assert.notNull(authorizationRequest, "authorizationRequest cannot be null");
71+
Assert.notNull(exchange, "exchange cannot be null");
6672
// @formatter:off
67-
return saveStateToAuthorizationRequest(exchange)
68-
.doOnNext((stateToAuthorizationRequest) -> stateToAuthorizationRequest
69-
.put(authorizationRequest.getState(), authorizationRequest))
73+
return getSessionAttributes(exchange)
74+
.doOnNext((sessionAttrs) -> {
75+
if (this.allowMultipleAuthorizationRequests) {
76+
Map<String, OAuth2AuthorizationRequest> authorizationRequests = this.getAuthorizationRequests(
77+
sessionAttrs);
78+
authorizationRequests.put(authorizationRequest.getState(), authorizationRequest);
79+
sessionAttrs.put(this.sessionAttributeName, authorizationRequests);
80+
}
81+
else {
82+
sessionAttrs.put(this.sessionAttributeName, authorizationRequest);
83+
}
84+
})
7085
.then();
7186
// @formatter:on
7287
}
@@ -78,30 +93,21 @@ public Mono<OAuth2AuthorizationRequest> removeAuthorizationRequest(ServerWebExch
7893
return Mono.empty();
7994
}
8095
// @formatter:off
81-
return exchange.getSession()
82-
.map(WebSession::getAttributes)
83-
.handle((sessionAttrs, sink) -> {
84-
Map<String, OAuth2AuthorizationRequest> stateToAuthzRequest = sessionAttrsMapStateToAuthorizationRequest(
96+
return getSessionAttributes(exchange)
97+
.flatMap((sessionAttrs) -> {
98+
Map<String, OAuth2AuthorizationRequest> authorizationRequests = this.getAuthorizationRequests(
8599
sessionAttrs);
86-
if (stateToAuthzRequest == null) {
87-
sink.complete();
88-
return;
89-
}
90-
OAuth2AuthorizationRequest removedValue = stateToAuthzRequest.remove(state);
91-
if (stateToAuthzRequest.isEmpty()) {
100+
OAuth2AuthorizationRequest originalRequest = authorizationRequests.remove(state);
101+
if (authorizationRequests.isEmpty()) {
92102
sessionAttrs.remove(this.sessionAttributeName);
93103
}
94-
else if (removedValue != null) {
95-
// gh-7327 Overwrite the existing Map to ensure the state is saved for
96-
// distributed sessions
97-
sessionAttrs.put(this.sessionAttributeName, stateToAuthzRequest);
98-
}
99-
if (removedValue == null) {
100-
sink.complete();
104+
else if (authorizationRequests.size() == 1) {
105+
sessionAttrs.put(this.sessionAttributeName, authorizationRequests.values().iterator().next());
101106
}
102107
else {
103-
sink.next(removedValue);
108+
sessionAttrs.put(this.sessionAttributeName, authorizationRequests);
104109
}
110+
return Mono.justOrEmpty(originalRequest);
105111
});
106112
// @formatter:on
107113
}
@@ -120,36 +126,41 @@ private Mono<Map<String, Object>> getSessionAttributes(ServerWebExchange exchang
120126
return exchange.getSession().map(WebSession::getAttributes);
121127
}
122128

123-
private Mono<Map<String, OAuth2AuthorizationRequest>> getStateToAuthorizationRequest(ServerWebExchange exchange) {
124-
Assert.notNull(exchange, "exchange cannot be null");
125-
126-
// @formatter:off
127-
return getSessionAttributes(exchange)
128-
.flatMap((sessionAttrs) -> Mono.justOrEmpty(this.sessionAttrsMapStateToAuthorizationRequest(sessionAttrs)));
129-
// @formatter:on
130-
}
131-
132-
private Mono<Map<String, OAuth2AuthorizationRequest>> saveStateToAuthorizationRequest(ServerWebExchange exchange) {
133-
Assert.notNull(exchange, "exchange cannot be null");
134-
// @formatter:off
135-
return getSessionAttributes(exchange)
136-
.doOnNext((sessionAttrs) -> {
137-
Object stateToAuthzRequest = sessionAttrs.get(this.sessionAttributeName);
138-
if (stateToAuthzRequest == null) {
139-
stateToAuthzRequest = new HashMap<String, OAuth2AuthorizationRequest>();
140-
}
141-
// No matter stateToAuthzRequest was in session or not, we should always put
142-
// it into session again
143-
// in case of redis or hazelcast session. #6215
144-
sessionAttrs.put(this.sessionAttributeName, stateToAuthzRequest);
145-
})
146-
.flatMap((sessionAttrs) -> Mono.justOrEmpty(this.sessionAttrsMapStateToAuthorizationRequest(sessionAttrs)));
147-
// @formatter:on
129+
private Map<String, OAuth2AuthorizationRequest> getAuthorizationRequests(Map<String, Object> sessionAttrs) {
130+
Object sessionAttributeValue = sessionAttrs.get(this.sessionAttributeName);
131+
if (sessionAttributeValue == null) {
132+
return new HashMap<>();
133+
}
134+
else if (sessionAttributeValue instanceof OAuth2AuthorizationRequest) {
135+
OAuth2AuthorizationRequest oauth2AuthorizationRequest = (OAuth2AuthorizationRequest) sessionAttributeValue;
136+
Map<String, OAuth2AuthorizationRequest> authorizationRequests = new HashMap<>(1);
137+
authorizationRequests.put(oauth2AuthorizationRequest.getState(), oauth2AuthorizationRequest);
138+
return authorizationRequests;
139+
}
140+
else if (sessionAttributeValue instanceof Map) {
141+
@SuppressWarnings("unchecked")
142+
Map<String, OAuth2AuthorizationRequest> authorizationRequests = (Map<String, OAuth2AuthorizationRequest>) sessionAttrs
143+
.get(this.sessionAttributeName);
144+
return authorizationRequests;
145+
}
146+
else {
147+
throw new IllegalStateException(
148+
"authorizationRequests is supposed to be a Map or OAuth2AuthorizationRequest but actually is a "
149+
+ sessionAttributeValue.getClass());
150+
}
148151
}
149152

150-
private Map<String, OAuth2AuthorizationRequest> sessionAttrsMapStateToAuthorizationRequest(
151-
Map<String, Object> sessionAttrs) {
152-
return (Map<String, OAuth2AuthorizationRequest>) sessionAttrs.get(this.sessionAttributeName);
153+
/**
154+
* Configure if multiple {@link OAuth2AuthorizationRequest}s should be stored per
155+
* session. Default is false (not allow multiple {@link OAuth2AuthorizationRequest}
156+
* per session).
157+
* @param allowMultipleAuthorizationRequests true allows more than one
158+
* {@link OAuth2AuthorizationRequest} to be stored per session.
159+
* @since 5.5
160+
*/
161+
@Deprecated
162+
public void setAllowMultipleAuthorizationRequests(boolean allowMultipleAuthorizationRequests) {
163+
this.allowMultipleAuthorizationRequests = allowMultipleAuthorizationRequests;
153164
}
154165

155166
}

0 commit comments

Comments
 (0)