15
15
*/
16
16
package org .springframework .security .oauth2 .server .authorization .config .annotation .web .configurers ;
17
17
18
+ import java .util .ArrayList ;
19
+ import java .util .List ;
20
+ import java .util .function .Consumer ;
18
21
import java .util .function .Function ;
19
22
20
23
import org .springframework .http .HttpMethod ;
21
24
import org .springframework .security .authentication .AuthenticationManager ;
25
+ import org .springframework .security .authentication .AuthenticationProvider ;
22
26
import org .springframework .security .config .annotation .ObjectPostProcessor ;
23
27
import org .springframework .security .config .annotation .web .builders .HttpSecurity ;
24
28
import org .springframework .security .oauth2 .core .OAuth2AccessToken ;
29
+ import org .springframework .security .oauth2 .core .OAuth2AuthenticationException ;
30
+ import org .springframework .security .oauth2 .core .OAuth2Error ;
25
31
import org .springframework .security .oauth2 .core .oidc .OidcIdToken ;
26
32
import org .springframework .security .oauth2 .core .oidc .OidcUserInfo ;
27
33
import org .springframework .security .oauth2 .server .authorization .oidc .authentication .OidcUserInfoAuthenticationContext ;
30
36
import org .springframework .security .oauth2 .server .authorization .oidc .web .OidcUserInfoEndpointFilter ;
31
37
import org .springframework .security .oauth2 .server .authorization .settings .AuthorizationServerSettings ;
32
38
import org .springframework .security .web .access .intercept .FilterSecurityInterceptor ;
39
+ import org .springframework .security .web .authentication .AuthenticationFailureHandler ;
40
+ import org .springframework .security .web .authentication .AuthenticationSuccessHandler ;
33
41
import org .springframework .security .web .util .matcher .AntPathRequestMatcher ;
34
42
import org .springframework .security .web .util .matcher .OrRequestMatcher ;
35
43
import org .springframework .security .web .util .matcher .RequestMatcher ;
44
+ import org .springframework .util .Assert ;
36
45
37
46
/**
38
47
* Configurer for OpenID Connect 1.0 UserInfo Endpoint.
39
48
*
40
49
* @author Steve Riesenberg
50
+ * @author Daniel Garnier-Moiroux
41
51
* @since 0.2.1
42
52
* @see OidcConfigurer#userInfoEndpoint
43
53
* @see OidcUserInfoEndpointFilter
44
54
*/
45
55
public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configurer {
46
56
private RequestMatcher requestMatcher ;
47
57
private Function <OidcUserInfoAuthenticationContext , OidcUserInfo > userInfoMapper ;
58
+ private final List <AuthenticationProvider > authenticationProviders = new ArrayList <>();
59
+ private Consumer <List <AuthenticationProvider >> authenticationProvidersConsumer = (authenticationProviders ) -> {};
60
+ private AuthenticationSuccessHandler userInfoResponseHandler ;
61
+ private AuthenticationFailureHandler errorResponseHandler ;
48
62
49
63
/**
50
64
* Restrict for internal use only.
@@ -74,6 +88,61 @@ public OidcUserInfoEndpointConfigurer userInfoMapper(Function<OidcUserInfoAuthen
74
88
return this ;
75
89
}
76
90
91
+ /**
92
+ * Adds an {@link AuthenticationProvider} used for authenticating a type of {@link OidcUserInfoAuthenticationToken}.
93
+ *
94
+ * @param authenticationProvider a {@link AuthenticationProvider} used for authenticating a type of {@link OidcUserInfoAuthenticationToken}
95
+ * @return the {@link OidcUserInfoEndpointConfigurer} for further configuration
96
+ * @since 0.4.0
97
+ */
98
+ public OidcUserInfoEndpointConfigurer authenticationProvider (AuthenticationProvider authenticationProvider ) {
99
+ Assert .notNull (authenticationProvider , "authenticationProvider cannot be null" );
100
+ this .authenticationProviders .add (authenticationProvider );
101
+ return this ;
102
+ }
103
+
104
+ /**
105
+ * Sets the {@code Consumer} providing access to the {@code List} of default
106
+ * and (optionally) added {@link #authenticationProvider(AuthenticationProvider) AuthenticationProvider}'s
107
+ * allowing the ability to add, remove, or customize a specific {@link AuthenticationProvider}.
108
+ *
109
+ * @param authenticationProvidersConsumer the {@code Consumer} providing access to the {@code List} of default and (optionally) added {@link AuthenticationProvider}'s
110
+ * @return the {@link OidcUserInfoEndpointConfigurer} for further configuration
111
+ * @since 0.4.0
112
+ */
113
+ public OidcUserInfoEndpointConfigurer authenticationProviders (
114
+ Consumer <List <AuthenticationProvider >> authenticationProvidersConsumer ) {
115
+ Assert .notNull (authenticationProvidersConsumer , "authenticationProvidersConsumer cannot be null" );
116
+ this .authenticationProvidersConsumer = authenticationProvidersConsumer ;
117
+ return this ;
118
+ }
119
+
120
+ /**
121
+ * Sets the {@link AuthenticationSuccessHandler} used for handling an {@link OidcUserInfoAuthenticationToken} and
122
+ * returning the {@link OidcUserInfo User Info Response}.
123
+ *
124
+ * @param userInfoResponseHandler the {@link AuthenticationSuccessHandler} used for handling an {@link OidcUserInfoAuthenticationToken}
125
+ * @return the {@link OidcUserInfoEndpointConfigurer} for further configuration
126
+ * @since 0.4.0
127
+ */
128
+ public OidcUserInfoEndpointConfigurer userInfoResponseHandler (AuthenticationSuccessHandler userInfoResponseHandler ) {
129
+ this .userInfoResponseHandler = userInfoResponseHandler ;
130
+ return this ;
131
+ }
132
+
133
+ /**
134
+ * Sets the {@link AuthenticationFailureHandler} used for handling an {@link OAuth2AuthenticationException} and
135
+ * returning the {@link OAuth2Error Error Response}.
136
+ *
137
+ * @param errorResponseHandler the {@link AuthenticationFailureHandler} used for handling an {@link OAuth2AuthenticationException}
138
+ * @return the {@link OidcUserInfoEndpointConfigurer} for further configuration
139
+ * @since 0.4.0
140
+ */
141
+ public OidcUserInfoEndpointConfigurer errorResponseHandler (AuthenticationFailureHandler errorResponseHandler ) {
142
+ this .errorResponseHandler = errorResponseHandler ;
143
+ return null ;
144
+ }
145
+
77
146
@ Override
78
147
void init (HttpSecurity httpSecurity ) {
79
148
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils .getAuthorizationServerSettings (httpSecurity );
@@ -82,13 +151,24 @@ void init(HttpSecurity httpSecurity) {
82
151
new AntPathRequestMatcher (userInfoEndpointUri , HttpMethod .GET .name ()),
83
152
new AntPathRequestMatcher (userInfoEndpointUri , HttpMethod .POST .name ()));
84
153
85
- OidcUserInfoAuthenticationProvider oidcUserInfoAuthenticationProvider =
86
- new OidcUserInfoAuthenticationProvider (
87
- OAuth2ConfigurerUtils .getAuthorizationService (httpSecurity ));
154
+ List <AuthenticationProvider > authenticationProviders = createDefaultAuthenticationProviders (httpSecurity );
155
+
88
156
if (this .userInfoMapper != null ) {
89
- oidcUserInfoAuthenticationProvider .setUserInfoMapper (this .userInfoMapper );
157
+ // @formatter:off
158
+ authenticationProviders .stream ()
159
+ .filter (OidcUserInfoAuthenticationProvider .class ::isInstance )
160
+ .map (OidcUserInfoAuthenticationProvider .class ::cast )
161
+ .forEach (provider -> provider .setUserInfoMapper (this .userInfoMapper ));
162
+ // @formatter:on
90
163
}
91
- httpSecurity .authenticationProvider (postProcess (oidcUserInfoAuthenticationProvider ));
164
+
165
+ if (!this .authenticationProviders .isEmpty ()) {
166
+ authenticationProviders .addAll (0 , this .authenticationProviders );
167
+ }
168
+ this .authenticationProvidersConsumer .accept (authenticationProviders );
169
+
170
+ authenticationProviders .forEach (authenticationProvider ->
171
+ httpSecurity .authenticationProvider (postProcess (authenticationProvider )));
92
172
}
93
173
94
174
@ Override
@@ -100,6 +180,12 @@ void configure(HttpSecurity httpSecurity) {
100
180
new OidcUserInfoEndpointFilter (
101
181
authenticationManager ,
102
182
authorizationServerSettings .getOidcUserInfoEndpoint ());
183
+ if (this .userInfoResponseHandler != null ) {
184
+ oidcUserInfoEndpointFilter .setAuthenticationSuccessHandler (this .userInfoResponseHandler );
185
+ }
186
+ if (this .errorResponseHandler != null ) {
187
+ oidcUserInfoEndpointFilter .setAuthenticationFailureHandler (this .errorResponseHandler );
188
+ }
103
189
httpSecurity .addFilterAfter (postProcess (oidcUserInfoEndpointFilter ), FilterSecurityInterceptor .class );
104
190
}
105
191
@@ -108,4 +194,14 @@ RequestMatcher getRequestMatcher() {
108
194
return this .requestMatcher ;
109
195
}
110
196
197
+ private static List <AuthenticationProvider > createDefaultAuthenticationProviders (HttpSecurity httpSecurity ) {
198
+ List <AuthenticationProvider > authenticationProviders = new ArrayList <>();
199
+
200
+ OidcUserInfoAuthenticationProvider oidcUserInfoAuthenticationProvider = new OidcUserInfoAuthenticationProvider (
201
+ OAuth2ConfigurerUtils .getAuthorizationService (httpSecurity ));
202
+ authenticationProviders .add (oidcUserInfoAuthenticationProvider );
203
+
204
+ return authenticationProviders ;
205
+ }
206
+
111
207
}
0 commit comments