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,24 +47,42 @@ 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 (
51
54
ServerWebExchange exchange ) {
52
55
String state = getStateParameter (exchange );
53
56
if (state == null ) {
54
57
return Mono .empty ();
55
58
}
56
- return getStateToAuthorizationRequest (exchange )
57
- .filter (stateToAuthorizationRequest -> stateToAuthorizationRequest .containsKey (state ))
58
- .map (stateToAuthorizationRequest -> stateToAuthorizationRequest .get (state ));
59
+ // @formatter:off
60
+ return this .getSessionAttributes (exchange )
61
+ .filter ((sessionAttrs ) -> sessionAttrs .containsKey (this .sessionAttributeName ))
62
+ .map (this ::getAuthorizationRequests )
63
+ .filter ((stateToAuthorizationRequest ) -> stateToAuthorizationRequest .containsKey (state ))
64
+ .map ((stateToAuthorizationRequest ) -> stateToAuthorizationRequest .get (state ));
65
+ // @formatter:on
59
66
}
60
67
61
68
@ Override
62
69
public Mono <Void > saveAuthorizationRequest (
63
70
OAuth2AuthorizationRequest authorizationRequest , ServerWebExchange exchange ) {
64
71
Assert .notNull (authorizationRequest , "authorizationRequest cannot be null" );
65
- return saveStateToAuthorizationRequest (exchange )
66
- .doOnNext (stateToAuthorizationRequest -> stateToAuthorizationRequest .put (authorizationRequest .getState (), authorizationRequest ))
72
+ Assert .notNull (exchange , "exchange cannot be null" );
73
+ // @formatter:off
74
+ return getSessionAttributes (exchange )
75
+ .doOnNext ((sessionAttrs ) -> {
76
+ if (this .allowMultipleAuthorizationRequests ) {
77
+ Map <String , OAuth2AuthorizationRequest > authorizationRequests = this .getAuthorizationRequests (
78
+ sessionAttrs );
79
+ authorizationRequests .put (authorizationRequest .getState (), authorizationRequest );
80
+ sessionAttrs .put (this .sessionAttributeName , authorizationRequests );
81
+ }
82
+ else {
83
+ sessionAttrs .put (this .sessionAttributeName , authorizationRequest );
84
+ }
85
+ })
67
86
.then ();
68
87
}
69
88
@@ -74,27 +93,24 @@ public Mono<OAuth2AuthorizationRequest> removeAuthorizationRequest(
74
93
if (state == null ) {
75
94
return Mono .empty ();
76
95
}
77
- return exchange .getSession ()
78
- .map (WebSession ::getAttributes )
79
- .handle ((sessionAttrs , sink ) -> {
80
- Map <String , OAuth2AuthorizationRequest > stateToAuthzRequest = sessionAttrsMapStateToAuthorizationRequest (sessionAttrs );
81
- if (stateToAuthzRequest == null ) {
82
- sink .complete ();
83
- return ;
84
- }
85
- OAuth2AuthorizationRequest removedValue = stateToAuthzRequest .remove (state );
86
- if (stateToAuthzRequest .isEmpty ()) {
87
- 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 );
91
- }
92
- if (removedValue == null ) {
93
- sink .complete ();
94
- } else {
95
- sink .next (removedValue );
96
- }
97
- });
96
+ // @formatter:off
97
+ return getSessionAttributes (exchange )
98
+ .flatMap ((sessionAttrs ) -> {
99
+ Map <String , OAuth2AuthorizationRequest > authorizationRequests = this .getAuthorizationRequests (
100
+ sessionAttrs );
101
+ OAuth2AuthorizationRequest originalRequest = authorizationRequests .remove (state );
102
+ if (authorizationRequests .isEmpty ()) {
103
+ sessionAttrs .remove (this .sessionAttributeName );
104
+ }
105
+ else if (authorizationRequests .size () == 1 ) {
106
+ sessionAttrs .put (this .sessionAttributeName , authorizationRequests .values ().iterator ().next ());
107
+ }
108
+ else {
109
+ sessionAttrs .put (this .sessionAttributeName , authorizationRequests );
110
+ }
111
+ return Mono .justOrEmpty (originalRequest );
112
+ });
113
+ // @formatter:on
98
114
}
99
115
100
116
/**
@@ -111,31 +127,40 @@ private Mono<Map<String, Object>> getSessionAttributes(ServerWebExchange exchang
111
127
return exchange .getSession ().map (WebSession ::getAttributes );
112
128
}
113
129
114
- private Mono < Map <String , OAuth2AuthorizationRequest >> getStateToAuthorizationRequest ( ServerWebExchange exchange ) {
115
- Assert . notNull ( exchange , "exchange cannot be null" );
116
-
117
- return getSessionAttributes ( exchange )
118
- . flatMap ( sessionAttrs -> Mono . justOrEmpty ( this . sessionAttrsMapStateToAuthorizationRequest ( sessionAttrs )));
119
- }
120
-
121
- private Mono < Map <String , OAuth2AuthorizationRequest >> saveStateToAuthorizationRequest ( ServerWebExchange exchange ) {
122
- Assert . notNull ( exchange , "exchange cannot be null" );
123
-
124
- return getSessionAttributes ( exchange )
125
- . doOnNext ( sessionAttrs -> {
126
- Object stateToAuthzRequest = sessionAttrs . get ( this . sessionAttributeName );
127
-
128
- if ( stateToAuthzRequest == null ) {
129
- stateToAuthzRequest = new HashMap < String , OAuth2AuthorizationRequest >() ;
130
- }
131
-
132
- // No matter stateToAuthzRequest was in session or not, we should always put it into session again
133
- // in case of redis or hazelcast session. #6215
134
- sessionAttrs . put ( this . sessionAttributeName , stateToAuthzRequest );
135
- }). flatMap ( sessionAttrs -> Mono . justOrEmpty ( this . sessionAttrsMapStateToAuthorizationRequest ( sessionAttrs )));
130
+ private Map <String , OAuth2AuthorizationRequest > getAuthorizationRequests ( Map < String , Object > sessionAttrs ) {
131
+ Object sessionAttributeValue = sessionAttrs . get ( this . sessionAttributeName );
132
+ if ( sessionAttributeValue == null ) {
133
+ return new HashMap <>();
134
+ }
135
+ else if ( sessionAttributeValue instanceof OAuth2AuthorizationRequest ) {
136
+ OAuth2AuthorizationRequest oauth2AuthorizationRequest = ( OAuth2AuthorizationRequest ) sessionAttributeValue ;
137
+ Map <String , OAuth2AuthorizationRequest > authorizationRequests = new HashMap <>( 1 );
138
+ authorizationRequests . put ( oauth2AuthorizationRequest . getState (), oauth2AuthorizationRequest );
139
+ return authorizationRequests ;
140
+ }
141
+ else if ( sessionAttributeValue instanceof Map ) {
142
+ @ SuppressWarnings ( "unchecked" )
143
+ Map < String , OAuth2AuthorizationRequest > authorizationRequests = ( Map < String , OAuth2AuthorizationRequest >) sessionAttrs
144
+ . get ( this . sessionAttributeName );
145
+ return authorizationRequests ;
146
+ }
147
+ else {
148
+ throw new IllegalStateException (
149
+ "authorizationRequests is supposed to be a Map or OAuth2AuthorizationRequest but actually is a "
150
+ + sessionAttributeValue . getClass () );
151
+ }
136
152
}
137
153
138
- private Map <String , OAuth2AuthorizationRequest > sessionAttrsMapStateToAuthorizationRequest (Map <String , Object > sessionAttrs ) {
139
- return (Map <String , OAuth2AuthorizationRequest >) sessionAttrs .get (this .sessionAttributeName );
154
+ /**
155
+ * Configure if multiple {@link OAuth2AuthorizationRequest}s should be stored per
156
+ * session. Default is false (not allow multiple {@link OAuth2AuthorizationRequest}
157
+ * per session).
158
+ * @param allowMultipleAuthorizationRequests true allows more than one
159
+ * {@link OAuth2AuthorizationRequest} to be stored per session.
160
+ * @since 5.5
161
+ */
162
+ @ Deprecated
163
+ public void setAllowMultipleAuthorizationRequests (boolean allowMultipleAuthorizationRequests ) {
164
+ this .allowMultipleAuthorizationRequests = allowMultipleAuthorizationRequests ;
140
165
}
141
166
}
0 commit comments