24
24
import org .springframework .security .config .annotation .web .HttpSecurityBuilder ;
25
25
import org .springframework .security .config .annotation .web .configurers .AbstractHttpConfigurer ;
26
26
import org .springframework .security .config .annotation .web .configurers .ExceptionHandlingConfigurer ;
27
+ import org .springframework .security .crypto .key .AsymmetricKey ;
28
+ import org .springframework .security .crypto .key .CryptoKey ;
27
29
import org .springframework .security .crypto .key .CryptoKeySource ;
30
+ import org .springframework .security .crypto .key .SymmetricKey ;
28
31
import org .springframework .security .oauth2 .jose .jws .NimbusJwsEncoder ;
32
+ import org .springframework .security .oauth2 .jwt .JwtDecoder ;
33
+ import org .springframework .security .oauth2 .jwt .NimbusJwtDecoder ;
29
34
import org .springframework .security .oauth2 .server .authorization .InMemoryOAuth2AuthorizationService ;
30
35
import org .springframework .security .oauth2 .server .authorization .OAuth2AuthorizationService ;
31
36
import org .springframework .security .oauth2 .server .authorization .authentication .OAuth2AuthorizationCodeAuthenticationProvider ;
32
37
import org .springframework .security .oauth2 .server .authorization .authentication .OAuth2ClientAuthenticationProvider ;
33
38
import org .springframework .security .oauth2 .server .authorization .authentication .OAuth2ClientCredentialsAuthenticationProvider ;
34
39
import org .springframework .security .oauth2 .server .authorization .authentication .OAuth2RefreshTokenAuthenticationProvider ;
40
+ import org .springframework .security .oauth2 .server .authorization .authentication .OAuth2TokenIntrospectionAuthenticationProvider ;
35
41
import org .springframework .security .oauth2 .server .authorization .authentication .OAuth2TokenRevocationAuthenticationProvider ;
36
42
import org .springframework .security .oauth2 .server .authorization .client .RegisteredClientRepository ;
37
43
import org .springframework .security .oauth2 .server .authorization .config .ProviderSettings ;
38
44
import org .springframework .security .oauth2 .server .authorization .web .JwkSetEndpointFilter ;
39
45
import org .springframework .security .oauth2 .server .authorization .web .OAuth2AuthorizationEndpointFilter ;
40
46
import org .springframework .security .oauth2 .server .authorization .web .OAuth2ClientAuthenticationFilter ;
41
47
import org .springframework .security .oauth2 .server .authorization .web .OAuth2TokenEndpointFilter ;
48
+ import org .springframework .security .oauth2 .server .authorization .web .OAuth2TokenIntrospectionEndpointFilter ;
42
49
import org .springframework .security .oauth2 .server .authorization .web .OAuth2TokenRevocationEndpointFilter ;
43
50
import org .springframework .security .oauth2 .server .authorization .web .OidcProviderConfigurationEndpointFilter ;
44
51
import org .springframework .security .web .AuthenticationEntryPoint ;
55
62
import org .springframework .util .StringUtils ;
56
63
57
64
import java .net .URI ;
65
+ import java .security .Key ;
66
+ import java .security .interfaces .RSAPublicKey ;
67
+ import java .util .ArrayList ;
58
68
import java .util .Arrays ;
69
+ import java .util .Collection ;
59
70
import java .util .LinkedHashMap ;
60
71
import java .util .List ;
61
72
import java .util .Map ;
65
76
*
66
77
* @author Joe Grandja
67
78
* @author Daniel Garnier-Moiroux
79
+ * @author Gerardo Roza
68
80
* @since 0.0.1
69
81
* @see AbstractHttpConfigurer
70
82
* @see RegisteredClientRepository
71
83
* @see OAuth2AuthorizationService
72
84
* @see OAuth2AuthorizationEndpointFilter
73
85
* @see OAuth2TokenEndpointFilter
86
+ * @see OAuth2TokenIntrospectionEndpointFilter
74
87
* @see OAuth2TokenRevocationEndpointFilter
75
88
* @see JwkSetEndpointFilter
76
89
* @see OidcProviderConfigurationEndpointFilter
@@ -88,6 +101,8 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
88
101
HttpMethod .POST .name ()));
89
102
private final RequestMatcher tokenEndpointMatcher = new AntPathRequestMatcher (
90
103
OAuth2TokenEndpointFilter .DEFAULT_TOKEN_ENDPOINT_URI , HttpMethod .POST .name ());
104
+ private final RequestMatcher tokenIntrospectionMatcher = new AntPathRequestMatcher (
105
+ OAuth2TokenIntrospectionEndpointFilter .DEFAULT_TOKEN_INTROSPECTION_ENDPOINT_URI , HttpMethod .POST .name ());
91
106
private final RequestMatcher tokenRevocationEndpointMatcher = new AntPathRequestMatcher (
92
107
OAuth2TokenRevocationEndpointFilter .DEFAULT_TOKEN_REVOCATION_ENDPOINT_URI , HttpMethod .POST .name ());
93
108
private final RequestMatcher jwkSetEndpointMatcher = new AntPathRequestMatcher (
@@ -152,7 +167,7 @@ public List<RequestMatcher> getEndpointMatchers() {
152
167
// TODO Initialize matchers using URI's from ProviderSettings
153
168
return Arrays .asList (this .authorizationEndpointMatcher , this .tokenEndpointMatcher ,
154
169
this .tokenRevocationEndpointMatcher , this .jwkSetEndpointMatcher ,
155
- this .oidcProviderConfigurationEndpointMatcher );
170
+ this .oidcProviderConfigurationEndpointMatcher , this . tokenIntrospectionMatcher );
156
171
}
157
172
158
173
@ Override
@@ -192,11 +207,17 @@ public void init(B builder) {
192
207
getAuthorizationService (builder ));
193
208
builder .authenticationProvider (postProcess (tokenRevocationAuthenticationProvider ));
194
209
210
+ OAuth2TokenIntrospectionAuthenticationProvider tokenIntrospectionAuthenticationProvider =
211
+ new OAuth2TokenIntrospectionAuthenticationProvider (
212
+ getAuthorizationService (builder ), getJwtDecoders (builder ));
213
+ builder .authenticationProvider (postProcess (tokenIntrospectionAuthenticationProvider ));
214
+
195
215
ExceptionHandlingConfigurer <B > exceptionHandling = builder .getConfigurer (ExceptionHandlingConfigurer .class );
196
216
if (exceptionHandling != null ) {
197
217
LinkedHashMap <RequestMatcher , AuthenticationEntryPoint > entryPoints = new LinkedHashMap <>();
198
218
entryPoints .put (
199
- new OrRequestMatcher (this .tokenEndpointMatcher , this .tokenRevocationEndpointMatcher ),
219
+ new OrRequestMatcher (this .tokenEndpointMatcher , this .tokenRevocationEndpointMatcher ,
220
+ this .tokenIntrospectionMatcher ),
200
221
new HttpStatusEntryPoint (HttpStatus .UNAUTHORIZED ));
201
222
DelegatingAuthenticationEntryPoint authenticationEntryPoint =
202
223
new DelegatingAuthenticationEntryPoint (entryPoints );
@@ -229,7 +250,8 @@ public void configure(B builder) {
229
250
OAuth2ClientAuthenticationFilter clientAuthenticationFilter =
230
251
new OAuth2ClientAuthenticationFilter (
231
252
authenticationManager ,
232
- new OrRequestMatcher (this .tokenEndpointMatcher , this .tokenRevocationEndpointMatcher ));
253
+ new OrRequestMatcher (this .tokenEndpointMatcher , this .tokenRevocationEndpointMatcher ,
254
+ this .tokenIntrospectionMatcher ));
233
255
builder .addFilterAfter (postProcess (clientAuthenticationFilter ), AbstractPreAuthenticatedProcessingFilter .class );
234
256
235
257
OAuth2AuthorizationEndpointFilter authorizationEndpointFilter =
@@ -251,6 +273,12 @@ public void configure(B builder) {
251
273
authenticationManager ,
252
274
providerSettings .tokenRevocationEndpoint ());
253
275
builder .addFilterAfter (postProcess (tokenRevocationEndpointFilter ), OAuth2TokenEndpointFilter .class );
276
+
277
+ OAuth2TokenIntrospectionEndpointFilter tokenIntrospectionEndpointFilter =
278
+ new OAuth2TokenIntrospectionEndpointFilter (
279
+ authenticationManager ,
280
+ providerSettings .tokenIntrospectionEndpoint ());
281
+ builder .addFilterAfter (postProcess (tokenIntrospectionEndpointFilter ), OAuth2TokenEndpointFilter .class );
254
282
}
255
283
256
284
private static <B extends HttpSecurityBuilder <B >> RegisteredClientRepository getRegisteredClientRepository (B builder ) {
@@ -278,6 +306,20 @@ private static <B extends HttpSecurityBuilder<B>> OAuth2AuthorizationService get
278
306
return authorizationService ;
279
307
}
280
308
309
+ private static <B extends HttpSecurityBuilder <B >> Collection <JwtDecoder > getJwtDecoders (B builder ) {
310
+ Collection <JwtDecoder > jwtDecoders = new ArrayList <>();
311
+ for (CryptoKey <? extends Key > cryptoKey : getKeySource (builder ).getKeys ()) {
312
+ if (AsymmetricKey .class .isAssignableFrom (cryptoKey .getClass ())
313
+ && RSAPublicKey .class .isAssignableFrom (((AsymmetricKey ) cryptoKey ).getPublicKey ().getClass ())) {
314
+ jwtDecoders .add (NimbusJwtDecoder
315
+ .withPublicKey ((RSAPublicKey ) ((AsymmetricKey ) cryptoKey ).getPublicKey ()).build ());
316
+ } else if (SymmetricKey .class .isAssignableFrom (cryptoKey .getClass ())) {
317
+ jwtDecoders .add (NimbusJwtDecoder .withSecretKey (((SymmetricKey ) cryptoKey ).getKey ()).build ());
318
+ }
319
+ }
320
+ return jwtDecoders ;
321
+ }
322
+
281
323
private static <B extends HttpSecurityBuilder <B >> OAuth2AuthorizationService getAuthorizationServiceBean (B builder ) {
282
324
Map <String , OAuth2AuthorizationService > authorizationServiceMap = BeanFactoryUtils .beansOfTypeIncludingAncestors (
283
325
builder .getSharedObject (ApplicationContext .class ), OAuth2AuthorizationService .class );
0 commit comments