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 ;
28
+ import org .springframework .security .core .Authentication ;
29
+ import org .springframework .security .core .context .SecurityContextHolder ;
24
30
import org .springframework .security .oauth2 .core .OAuth2AccessToken ;
31
+ import org .springframework .security .oauth2 .core .OAuth2AuthenticationException ;
32
+ import org .springframework .security .oauth2 .core .OAuth2Error ;
25
33
import org .springframework .security .oauth2 .core .oidc .OidcIdToken ;
26
34
import org .springframework .security .oauth2 .core .oidc .OidcUserInfo ;
27
35
import org .springframework .security .oauth2 .server .authorization .oidc .authentication .OidcUserInfoAuthenticationContext ;
28
36
import org .springframework .security .oauth2 .server .authorization .oidc .authentication .OidcUserInfoAuthenticationProvider ;
29
37
import org .springframework .security .oauth2 .server .authorization .oidc .authentication .OidcUserInfoAuthenticationToken ;
30
38
import org .springframework .security .oauth2 .server .authorization .oidc .web .OidcUserInfoEndpointFilter ;
31
39
import org .springframework .security .oauth2 .server .authorization .settings .AuthorizationServerSettings ;
40
+ import org .springframework .security .oauth2 .server .authorization .web .authentication .DelegatingAuthenticationConverter ;
32
41
import org .springframework .security .web .access .intercept .FilterSecurityInterceptor ;
42
+ import org .springframework .security .web .authentication .AuthenticationConverter ;
43
+ import org .springframework .security .web .authentication .AuthenticationFailureHandler ;
44
+ import org .springframework .security .web .authentication .AuthenticationSuccessHandler ;
33
45
import org .springframework .security .web .util .matcher .AntPathRequestMatcher ;
34
46
import org .springframework .security .web .util .matcher .OrRequestMatcher ;
35
47
import org .springframework .security .web .util .matcher .RequestMatcher ;
48
+ import org .springframework .util .Assert ;
36
49
37
50
/**
38
51
* Configurer for OpenID Connect 1.0 UserInfo Endpoint.
39
52
*
40
53
* @author Steve Riesenberg
54
+ * @author Daniel Garnier-Moiroux
41
55
* @since 0.2.1
42
56
* @see OidcConfigurer#userInfoEndpoint
43
57
* @see OidcUserInfoEndpointFilter
44
58
*/
45
59
public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configurer {
46
60
private RequestMatcher requestMatcher ;
61
+ private final List <AuthenticationConverter > authenticationConverters = new ArrayList <>();
62
+ private Consumer <List <AuthenticationConverter >> authenticationConvertersConsumer = (authenticationConverters ) -> {};
63
+ private final List <AuthenticationProvider > authenticationProviders = new ArrayList <>();
64
+ private Consumer <List <AuthenticationProvider >> authenticationProvidersConsumer = (authenticationProviders ) -> {};
65
+ private AuthenticationSuccessHandler userInfoResponseHandler ;
66
+ private AuthenticationFailureHandler errorResponseHandler ;
47
67
private Function <OidcUserInfoAuthenticationContext , OidcUserInfo > userInfoMapper ;
48
68
49
69
/**
@@ -54,22 +74,82 @@ public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configur
54
74
}
55
75
56
76
/**
57
- * Sets the {@link Function} used to extract claims from {@link OidcUserInfoAuthenticationContext}
58
- * to an instance of {@link OidcUserInfo} for the UserInfo response.
77
+ * Adds an {@link AuthenticationProvider} used for authenticating a type of {@link OidcUserInfoAuthenticationToken}.
78
+ *
79
+ * @param authenticationProvider a {@link AuthenticationProvider} used for authenticating a type of {@link OidcUserInfoAuthenticationToken}
80
+ * @return the {@link OidcUserInfoEndpointConfigurer} for further configuration
81
+ * @since 0.4.0
82
+ */
83
+ public OidcUserInfoEndpointConfigurer authenticationProvider (AuthenticationProvider authenticationProvider ) {
84
+ Assert .notNull (authenticationProvider , "authenticationProvider cannot be null" );
85
+ this .authenticationProviders .add (authenticationProvider );
86
+ return this ;
87
+ }
88
+
89
+ /**
90
+ * Sets the {@code Consumer} providing access to the {@code List} of default
91
+ * and (optionally) added {@link #authenticationProvider(AuthenticationProvider) AuthenticationProvider}'s
92
+ * allowing the ability to add, remove, or customize a specific {@link AuthenticationProvider}.
93
+ *
94
+ * @param authenticationProvidersConsumer the {@code Consumer} providing access to the {@code List} of default and (optionally) added {@link AuthenticationProvider}'s
95
+ * @return the {@link OidcUserInfoEndpointConfigurer} for further configuration
96
+ * @since 0.4.0
97
+ */
98
+ public OidcUserInfoEndpointConfigurer authenticationProviders (
99
+ Consumer <List <AuthenticationProvider >> authenticationProvidersConsumer ) {
100
+ Assert .notNull (authenticationProvidersConsumer , "authenticationProvidersConsumer cannot be null" );
101
+ this .authenticationProvidersConsumer = authenticationProvidersConsumer ;
102
+ return this ;
103
+ }
104
+
105
+ /**
106
+ * Sets the {@link AuthenticationSuccessHandler} used for handling an {@link OidcUserInfoAuthenticationToken} and
107
+ * returning the {@link OidcUserInfo User Info Response}.
108
+ *
109
+ * @param userInfoResponseHandler the {@link AuthenticationSuccessHandler} used for handling an {@link OidcUserInfoAuthenticationToken}
110
+ * @return the {@link OidcUserInfoEndpointConfigurer} for further configuration
111
+ * @since 0.4.0
112
+ */
113
+ public OidcUserInfoEndpointConfigurer userInfoResponseHandler (AuthenticationSuccessHandler userInfoResponseHandler ) {
114
+ this .userInfoResponseHandler = userInfoResponseHandler ;
115
+ return this ;
116
+ }
117
+
118
+ /**
119
+ * Sets the {@link AuthenticationFailureHandler} used for handling an {@link OAuth2AuthenticationException} and
120
+ * returning the {@link OAuth2Error Error Response}.
121
+ *
122
+ * @param errorResponseHandler the {@link AuthenticationFailureHandler} used for handling an {@link OAuth2AuthenticationException}
123
+ * @return the {@link OidcUserInfoEndpointConfigurer} for further configuration
124
+ * @since 0.4.0
125
+ */
126
+ public OidcUserInfoEndpointConfigurer errorResponseHandler (AuthenticationFailureHandler errorResponseHandler ) {
127
+ this .errorResponseHandler = errorResponseHandler ;
128
+ return null ;
129
+ }
130
+
131
+ /**
132
+ * Sets the {@link Function} used to extract claims from
133
+ * {@link OidcUserInfoAuthenticationContext} to an instance of {@link OidcUserInfo}
134
+ * for the UserInfo response.
59
135
*
60
136
* <p>
61
- * The {@link OidcUserInfoAuthenticationContext} gives the mapper access to the {@link OidcUserInfoAuthenticationToken},
62
- * as well as, the following context attributes:
137
+ * The {@link OidcUserInfoAuthenticationContext} gives the mapper access to the
138
+ * {@link OidcUserInfoAuthenticationToken}, as well as, the following context
139
+ * attributes:
63
140
* <ul>
64
- * <li>{@link OidcUserInfoAuthenticationContext#getAccessToken()} containing the bearer token used to make the request.</li>
65
- * <li>{@link OidcUserInfoAuthenticationContext#getAuthorization()} containing the {@link OidcIdToken} and
66
- * {@link OAuth2AccessToken} associated with the bearer token used to make the request.</li>
141
+ * <li>{@link OidcUserInfoAuthenticationContext#getAccessToken()} containing the
142
+ * bearer token used to make the request.</li>
143
+ * <li>{@link OidcUserInfoAuthenticationContext#getAuthorization()} containing the
144
+ * {@link OidcIdToken} and {@link OAuth2AccessToken} associated with the bearer token
145
+ * used to make the request.</li>
67
146
* </ul>
68
- *
69
- * @param userInfoMapper the {@link Function} used to extract claims from {@link OidcUserInfoAuthenticationContext} to an instance of {@link OidcUserInfo}
147
+ * @param userInfoMapper the {@link Function} used to extract claims from
148
+ * {@link OidcUserInfoAuthenticationContext} to an instance of {@link OidcUserInfo}
70
149
* @return the {@link OidcUserInfoEndpointConfigurer} for further configuration
71
150
*/
72
- public OidcUserInfoEndpointConfigurer userInfoMapper (Function <OidcUserInfoAuthenticationContext , OidcUserInfo > userInfoMapper ) {
151
+ public OidcUserInfoEndpointConfigurer userInfoMapper (
152
+ Function <OidcUserInfoAuthenticationContext , OidcUserInfo > userInfoMapper ) {
73
153
this .userInfoMapper = userInfoMapper ;
74
154
return this ;
75
155
}
@@ -82,13 +162,15 @@ void init(HttpSecurity httpSecurity) {
82
162
new AntPathRequestMatcher (userInfoEndpointUri , HttpMethod .GET .name ()),
83
163
new AntPathRequestMatcher (userInfoEndpointUri , HttpMethod .POST .name ()));
84
164
85
- OidcUserInfoAuthenticationProvider oidcUserInfoAuthenticationProvider =
86
- new OidcUserInfoAuthenticationProvider (
87
- OAuth2ConfigurerUtils .getAuthorizationService (httpSecurity ));
88
- if (this .userInfoMapper != null ) {
89
- oidcUserInfoAuthenticationProvider .setUserInfoMapper (this .userInfoMapper );
165
+ List <AuthenticationProvider > authenticationProviders = createDefaultAuthenticationProviders (httpSecurity );
166
+
167
+ if (!this .authenticationProviders .isEmpty ()) {
168
+ authenticationProviders .addAll (0 , this .authenticationProviders );
90
169
}
91
- httpSecurity .authenticationProvider (postProcess (oidcUserInfoAuthenticationProvider ));
170
+ this .authenticationProvidersConsumer .accept (authenticationProviders );
171
+
172
+ authenticationProviders .forEach (authenticationProvider ->
173
+ httpSecurity .authenticationProvider (postProcess (authenticationProvider )));
92
174
}
93
175
94
176
@ Override
@@ -100,6 +182,15 @@ void configure(HttpSecurity httpSecurity) {
100
182
new OidcUserInfoEndpointFilter (
101
183
authenticationManager ,
102
184
authorizationServerSettings .getOidcUserInfoEndpoint ());
185
+ List <AuthenticationConverter > authenticationConverters = createDefaultAuthenticationConverters ();
186
+ oidcUserInfoEndpointFilter .setAuthenticationConverter (
187
+ new DelegatingAuthenticationConverter (authenticationConverters ));
188
+ if (this .userInfoResponseHandler != null ) {
189
+ oidcUserInfoEndpointFilter .setAuthenticationSuccessHandler (this .userInfoResponseHandler );
190
+ }
191
+ if (this .errorResponseHandler != null ) {
192
+ oidcUserInfoEndpointFilter .setAuthenticationFailureHandler (this .errorResponseHandler );
193
+ }
103
194
httpSecurity .addFilterAfter (postProcess (oidcUserInfoEndpointFilter ), FilterSecurityInterceptor .class );
104
195
}
105
196
@@ -108,4 +199,29 @@ RequestMatcher getRequestMatcher() {
108
199
return this .requestMatcher ;
109
200
}
110
201
202
+ private static List <AuthenticationConverter > createDefaultAuthenticationConverters () {
203
+ List <AuthenticationConverter > authenticationConverters = new ArrayList <>();
204
+ authenticationConverters .add (
205
+ (request ) -> {
206
+ Authentication authentication = SecurityContextHolder .getContext ().getAuthentication ();
207
+ return new OidcUserInfoAuthenticationToken (authentication );
208
+ }
209
+ );
210
+ return authenticationConverters ;
211
+ }
212
+
213
+ private List <AuthenticationProvider > createDefaultAuthenticationProviders (HttpSecurity httpSecurity ) {
214
+ List <AuthenticationProvider > authenticationProviders = new ArrayList <>();
215
+
216
+ OidcUserInfoAuthenticationProvider oidcUserInfoAuthenticationProvider = new OidcUserInfoAuthenticationProvider (
217
+ OAuth2ConfigurerUtils .getAuthorizationService (httpSecurity ));
218
+ if (this .userInfoMapper != null ) {
219
+ oidcUserInfoAuthenticationProvider .setUserInfoMapper (this .userInfoMapper );
220
+ }
221
+ authenticationProviders .add (oidcUserInfoAuthenticationProvider );
222
+
223
+ return authenticationProviders ;
224
+ }
225
+
226
+
111
227
}
0 commit comments