1
1
/*
2
- * Copyright 2002-2019 the original author or authors.
2
+ * Copyright 2002-2021 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
34
34
* {@link OAuth2AuthorizationRequest} in the {@code WebSession}.
35
35
*
36
36
* @author Rob Winch
37
+ * @author Steve Riesenberg
37
38
* @since 5.1
38
39
* @see AuthorizationRequestRepository
39
40
* @see OAuth2AuthorizationRequest
@@ -46,14 +47,18 @@ public final class WebSessionOAuth2ServerAuthorizationRequestRepository
46
47
47
48
private final String sessionAttributeName = DEFAULT_AUTHORIZATION_REQUEST_ATTR_NAME ;
48
49
50
+ private boolean allowMultipleAuthorizationRequests ;
51
+
49
52
@ Override
50
53
public Mono <OAuth2AuthorizationRequest > loadAuthorizationRequest (ServerWebExchange exchange ) {
51
54
String state = getStateParameter (exchange );
52
55
if (state == null ) {
53
56
return Mono .empty ();
54
57
}
55
58
// @formatter:off
56
- return getStateToAuthorizationRequest (exchange )
59
+ return this .getSessionAttributes (exchange )
60
+ .filter ((sessionAttrs ) -> sessionAttrs .containsKey (this .sessionAttributeName ))
61
+ .map (this ::getAuthorizationRequests )
57
62
.filter ((stateToAuthorizationRequest ) -> stateToAuthorizationRequest .containsKey (state ))
58
63
.map ((stateToAuthorizationRequest ) -> stateToAuthorizationRequest .get (state ));
59
64
// @formatter:on
@@ -63,10 +68,20 @@ public Mono<OAuth2AuthorizationRequest> loadAuthorizationRequest(ServerWebExchan
63
68
public Mono <Void > saveAuthorizationRequest (OAuth2AuthorizationRequest authorizationRequest ,
64
69
ServerWebExchange exchange ) {
65
70
Assert .notNull (authorizationRequest , "authorizationRequest cannot be null" );
71
+ Assert .notNull (exchange , "exchange cannot be null" );
66
72
// @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
+ })
70
85
.then ();
71
86
// @formatter:on
72
87
}
@@ -78,30 +93,21 @@ public Mono<OAuth2AuthorizationRequest> removeAuthorizationRequest(ServerWebExch
78
93
return Mono .empty ();
79
94
}
80
95
// @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 (
85
99
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 ()) {
92
102
sessionAttrs .remove (this .sessionAttributeName );
93
103
}
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 ());
101
106
}
102
107
else {
103
- sink . next ( removedValue );
108
+ sessionAttrs . put ( this . sessionAttributeName , authorizationRequests );
104
109
}
110
+ return Mono .justOrEmpty (originalRequest );
105
111
});
106
112
// @formatter:on
107
113
}
@@ -120,36 +126,41 @@ private Mono<Map<String, Object>> getSessionAttributes(ServerWebExchange exchang
120
126
return exchange .getSession ().map (WebSession ::getAttributes );
121
127
}
122
128
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
+ }
148
151
}
149
152
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 ;
153
164
}
154
165
155
166
}
0 commit comments