1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.springframework.security.oauth2.config.annotation.web.configurers;
17
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Set;
26
27 import org.springframework.beans.BeansException;
28 import org.springframework.beans.factory.ObjectFactory;
29 import org.springframework.http.HttpMethod;
30 import org.springframework.security.authentication.AuthenticationManager;
31 import org.springframework.security.authentication.AuthenticationProvider;
32 import org.springframework.security.authentication.ProviderManager;
33 import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
34 import org.springframework.security.core.userdetails.UserDetailsService;
35 import org.springframework.security.oauth2.common.OAuth2AccessToken;
36 import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
37 import org.springframework.security.oauth2.common.util.ProxyCreator;
38 import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
39 import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
40 import org.springframework.security.oauth2.provider.ClientDetailsService;
41 import org.springframework.security.oauth2.provider.CompositeTokenGranter;
42 import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
43 import org.springframework.security.oauth2.provider.OAuth2RequestValidator;
44 import org.springframework.security.oauth2.provider.TokenGranter;
45 import org.springframework.security.oauth2.provider.TokenRequest;
46 import org.springframework.security.oauth2.provider.approval.ApprovalStore;
47 import org.springframework.security.oauth2.provider.approval.ApprovalStoreUserApprovalHandler;
48 import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
49 import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler;
50 import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
51 import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter;
52 import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService;
53 import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
54 import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter;
55 import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
56 import org.springframework.security.oauth2.provider.endpoint.DefaultRedirectResolver;
57 import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping;
58 import org.springframework.security.oauth2.provider.endpoint.RedirectResolver;
59 import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
60 import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
61 import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter;
62 import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
63 import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter;
64 import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
65 import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator;
66 import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
67 import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
68 import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
69 import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
70 import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
71 import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
72 import org.springframework.security.oauth2.provider.token.TokenEnhancer;
73 import org.springframework.security.oauth2.provider.token.TokenStore;
74 import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
75 import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
76 import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
77 import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
78 import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
79 import org.springframework.web.context.request.WebRequestInterceptor;
80 import org.springframework.web.servlet.HandlerInterceptor;
81
82
83
84
85
86
87
88
89 public final class AuthorizationServerEndpointsConfigurer {
90
91 private AuthorizationServerTokenServices tokenServices;
92
93 private ConsumerTokenServices consumerTokenServices;
94
95 private AuthorizationCodeServices authorizationCodeServices;
96
97 private ResourceServerTokenServices resourceTokenServices;
98
99 private TokenStore tokenStore;
100
101 private TokenEnhancer tokenEnhancer;
102
103 private AccessTokenConverter accessTokenConverter;
104
105 private ApprovalStore approvalStore;
106
107 private TokenGranter tokenGranter;
108
109 private OAuth2RequestFactory requestFactory;
110
111 private OAuth2RequestValidator requestValidator;
112
113 private UserApprovalHandler userApprovalHandler;
114
115 private AuthenticationManager authenticationManager;
116
117 private ClientDetailsService clientDetailsService;
118
119 private String prefix;
120
121 private Map<String, String> patternMap = new HashMap<String, String>();
122
123 private Set<HttpMethod> allowedTokenEndpointRequestMethods = new HashSet<HttpMethod>();
124
125 private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping;
126
127 private boolean approvalStoreDisabled;
128
129 private List<Object> interceptors = new ArrayList<Object>();
130
131 private DefaultTokenServices defaultTokenServices;
132
133 private UserDetailsService userDetailsService;
134
135 private boolean tokenServicesOverride = false;
136
137 private boolean userDetailsServiceOverride = false;
138
139 private boolean reuseRefreshToken = true;
140
141 private WebResponseExceptionTranslator<OAuth2Exception> exceptionTranslator;
142
143 private RedirectResolver redirectResolver;
144
145 public AuthorizationServerTokenServices getTokenServices() {
146 return ProxyCreator.getProxy(AuthorizationServerTokenServices.class,
147 new ObjectFactory<AuthorizationServerTokenServices>() {
148 @Override
149 public AuthorizationServerTokenServices getObject() throws BeansException {
150 return tokenServices();
151 }
152 });
153 }
154
155 public TokenStore getTokenStore() {
156 return tokenStore();
157 }
158
159 public TokenEnhancer getTokenEnhancer() {
160 return tokenEnhancer;
161 }
162
163 public AccessTokenConverter getAccessTokenConverter() {
164 return accessTokenConverter();
165 }
166
167 public ApprovalStore getApprovalStore() {
168 return approvalStore;
169 }
170
171 public ClientDetailsService getClientDetailsService() {
172 return ProxyCreator.getProxy(ClientDetailsService.class, new ObjectFactory<ClientDetailsService>() {
173 @Override
174 public ClientDetailsService getObject() throws BeansException {
175 return clientDetailsService();
176 }
177 });
178 }
179
180 public OAuth2RequestFactory getOAuth2RequestFactory() {
181 return ProxyCreator.getProxy(OAuth2RequestFactory.class, new ObjectFactory<OAuth2RequestFactory>() {
182 @Override
183 public OAuth2RequestFactory getObject() throws BeansException {
184 return requestFactory();
185 }
186 });
187 }
188
189 public OAuth2RequestValidator getOAuth2RequestValidator() {
190 return requestValidator();
191 }
192
193 public UserApprovalHandler getUserApprovalHandler() {
194 return userApprovalHandler();
195 }
196
197 public AuthorizationServerEndpointsConfigurer tokenStore(TokenStore tokenStore) {
198 this.tokenStore = tokenStore;
199 return this;
200 }
201
202 public AuthorizationServerEndpointsConfigurer tokenEnhancer(TokenEnhancer tokenEnhancer) {
203 this.tokenEnhancer = tokenEnhancer;
204 return this;
205 }
206
207 public AuthorizationServerEndpointsConfigurer reuseRefreshTokens(boolean reuseRefreshToken) {
208 this.reuseRefreshToken = reuseRefreshToken;
209 return this;
210 }
211
212 public AuthorizationServerEndpointsConfigurer accessTokenConverter(AccessTokenConverter accessTokenConverter) {
213 this.accessTokenConverter = accessTokenConverter;
214 return this;
215 }
216
217 public AuthorizationServerEndpointsConfigurer tokenServices(AuthorizationServerTokenServices tokenServices) {
218 this.tokenServices = tokenServices;
219 if (tokenServices != null) {
220 this.tokenServicesOverride = true;
221 }
222 return this;
223 }
224
225 public AuthorizationServerEndpointsConfigurer redirectResolver(RedirectResolver redirectResolver) {
226 this.redirectResolver = redirectResolver;
227 return this;
228 }
229
230 public boolean isTokenServicesOverride() {
231 return tokenServicesOverride;
232 }
233
234 public boolean isUserDetailsServiceOverride() {
235 return userDetailsServiceOverride;
236 }
237
238 public AuthorizationServerEndpointsConfigurer userApprovalHandler(UserApprovalHandler approvalHandler) {
239 this.userApprovalHandler = approvalHandler;
240 return this;
241 }
242
243 public AuthorizationServerEndpointsConfigurer approvalStore(ApprovalStore approvalStore) {
244 if (approvalStoreDisabled) {
245 throw new IllegalStateException("ApprovalStore was disabled");
246 }
247 this.approvalStore = approvalStore;
248 return this;
249 }
250
251
252
253
254
255
256
257
258 public AuthorizationServerEndpointsConfigurer approvalStoreDisabled() {
259 this.approvalStoreDisabled = true;
260 return this;
261 }
262
263 public AuthorizationServerEndpointsConfigurer prefix(String prefix) {
264 this.prefix = prefix;
265 return this;
266 }
267
268 public AuthorizationServerEndpointsConfigurer pathMapping(String defaultPath, String customPath) {
269 this.patternMap.put(defaultPath, customPath);
270 return this;
271 }
272
273 public AuthorizationServerEndpointsConfigurer addInterceptor(HandlerInterceptor interceptor) {
274 this.interceptors.add(interceptor);
275 return this;
276 }
277
278 public AuthorizationServerEndpointsConfigurer addInterceptor(WebRequestInterceptor interceptor) {
279 this.interceptors.add(interceptor);
280 return this;
281 }
282
283 public AuthorizationServerEndpointsConfigurer exceptionTranslator(WebResponseExceptionTranslator<OAuth2Exception> exceptionTranslator) {
284 this.exceptionTranslator = exceptionTranslator;
285 return this;
286 }
287
288
289
290
291
292
293
294 public AuthorizationServerEndpointsConfigurer authenticationManager(AuthenticationManager authenticationManager) {
295 this.authenticationManager = authenticationManager;
296 return this;
297 }
298
299 public AuthorizationServerEndpointsConfigurer tokenGranter(TokenGranter tokenGranter) {
300 this.tokenGranter = tokenGranter;
301 return this;
302 }
303
304
305
306
307
308 public void setClientDetailsService(ClientDetailsService clientDetailsService) {
309 this.clientDetailsService = clientDetailsService;
310 }
311
312 public AuthorizationServerEndpointsConfigurer requestFactory(OAuth2RequestFactory requestFactory) {
313 this.requestFactory = requestFactory;
314 return this;
315 }
316
317 public AuthorizationServerEndpointsConfigurer requestValidator(OAuth2RequestValidator requestValidator) {
318 this.requestValidator = requestValidator;
319 return this;
320 }
321
322 public AuthorizationServerEndpointsConfigurer authorizationCodeServices(
323 AuthorizationCodeServices authorizationCodeServices) {
324 this.authorizationCodeServices = authorizationCodeServices;
325 return this;
326 }
327
328 public AuthorizationServerEndpointsConfigurer allowedTokenEndpointRequestMethods(HttpMethod... requestMethods) {
329 Collections.addAll(allowedTokenEndpointRequestMethods, requestMethods);
330 return this;
331 }
332
333 public AuthorizationServerEndpointsConfigurer userDetailsService(UserDetailsService userDetailsService) {
334 if (userDetailsService != null) {
335 this.userDetailsService = userDetailsService;
336 this.userDetailsServiceOverride = true;
337 }
338 return this;
339 }
340
341 public ConsumerTokenServices getConsumerTokenServices() {
342 return consumerTokenServices();
343 }
344
345 public ResourceServerTokenServices getResourceServerTokenServices() {
346 return resourceTokenServices();
347 }
348
349 public AuthorizationCodeServices getAuthorizationCodeServices() {
350 return authorizationCodeServices();
351 }
352
353 public Set<HttpMethod> getAllowedTokenEndpointRequestMethods() {
354 return allowedTokenEndpointRequestMethods();
355 }
356
357 public OAuth2RequestValidator getRequestValidator() {
358 return requestValidator();
359 }
360
361 public TokenGranter getTokenGranter() {
362 return tokenGranter();
363 }
364
365 public FrameworkEndpointHandlerMapping getFrameworkEndpointHandlerMapping() {
366 return frameworkEndpointHandlerMapping();
367 }
368
369 public WebResponseExceptionTranslator<OAuth2Exception> getExceptionTranslator() {
370 return exceptionTranslator();
371 }
372
373 public RedirectResolver getRedirectResolver() {
374 return redirectResolver();
375 }
376
377 private ResourceServerTokenServices resourceTokenServices() {
378 if (resourceTokenServices == null) {
379 if (tokenServices instanceof ResourceServerTokenServices) {
380 return (ResourceServerTokenServices) tokenServices;
381 }
382 resourceTokenServices = createDefaultTokenServices();
383 }
384 return resourceTokenServices;
385 }
386
387 private Set<HttpMethod> allowedTokenEndpointRequestMethods() {
388
389 if (allowedTokenEndpointRequestMethods.isEmpty()) {
390 allowedTokenEndpointRequestMethods.add(HttpMethod.POST);
391 }
392 return allowedTokenEndpointRequestMethods;
393 }
394
395 private ConsumerTokenServices consumerTokenServices() {
396 if (consumerTokenServices == null) {
397 if (tokenServices instanceof ConsumerTokenServices) {
398 return (ConsumerTokenServices) tokenServices;
399 }
400 consumerTokenServices = createDefaultTokenServices();
401 }
402 return consumerTokenServices;
403 }
404
405 private AuthorizationServerTokenServices tokenServices() {
406 if (tokenServices != null) {
407 return tokenServices;
408 }
409 this.tokenServices = createDefaultTokenServices();
410 return tokenServices;
411 }
412
413 public AuthorizationServerTokenServices getDefaultAuthorizationServerTokenServices() {
414 if (defaultTokenServices != null) {
415 return defaultTokenServices;
416 }
417 this.defaultTokenServices = createDefaultTokenServices();
418 return this.defaultTokenServices;
419 }
420
421 private DefaultTokenServices createDefaultTokenServices() {
422 DefaultTokenServices tokenServices = new DefaultTokenServices();
423 tokenServices.setTokenStore(tokenStore());
424 tokenServices.setSupportRefreshToken(true);
425 tokenServices.setReuseRefreshToken(reuseRefreshToken);
426 tokenServices.setClientDetailsService(clientDetailsService());
427 tokenServices.setTokenEnhancer(tokenEnhancer());
428 addUserDetailsService(tokenServices, this.userDetailsService);
429 return tokenServices;
430 }
431
432 private TokenEnhancer tokenEnhancer() {
433 if (this.tokenEnhancer == null && accessTokenConverter() instanceof JwtAccessTokenConverter) {
434 tokenEnhancer = (TokenEnhancer) accessTokenConverter;
435 }
436 return this.tokenEnhancer;
437 }
438
439 private AccessTokenConverter accessTokenConverter() {
440 if (this.accessTokenConverter == null) {
441 accessTokenConverter = new DefaultAccessTokenConverter();
442 }
443 return this.accessTokenConverter;
444 }
445
446 private TokenStore tokenStore() {
447 if (tokenStore == null) {
448 if (accessTokenConverter() instanceof JwtAccessTokenConverter) {
449 this.tokenStore = new JwtTokenStore((JwtAccessTokenConverter) accessTokenConverter());
450 }
451 else {
452 this.tokenStore = new InMemoryTokenStore();
453 }
454 }
455 return this.tokenStore;
456 }
457
458 private ApprovalStore approvalStore() {
459 if (approvalStore == null && tokenStore() != null && !isApprovalStoreDisabled()) {
460 TokenApprovalStore tokenApprovalStore = new TokenApprovalStore();
461 tokenApprovalStore.setTokenStore(tokenStore());
462 this.approvalStore = tokenApprovalStore;
463 }
464 return this.approvalStore;
465 }
466
467 private boolean isApprovalStoreDisabled() {
468 return approvalStoreDisabled || (tokenStore() instanceof JwtTokenStore);
469 }
470
471 private ClientDetailsService clientDetailsService() {
472 if (clientDetailsService == null) {
473 this.clientDetailsService = new InMemoryClientDetailsService();
474 }
475 if (this.defaultTokenServices != null) {
476 addUserDetailsService(defaultTokenServices, userDetailsService);
477 }
478 return this.clientDetailsService;
479 }
480
481 private void addUserDetailsService(DefaultTokenServices tokenServices, UserDetailsService userDetailsService) {
482 if (userDetailsService != null) {
483 PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
484 provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken>(
485 userDetailsService));
486 tokenServices
487 .setAuthenticationManager(new ProviderManager(Arrays.<AuthenticationProvider> asList(provider)));
488 }
489 }
490
491 private UserApprovalHandler userApprovalHandler() {
492 if (userApprovalHandler == null) {
493 if (approvalStore() != null) {
494 ApprovalStoreUserApprovalHandler handler = new ApprovalStoreUserApprovalHandler();
495 handler.setApprovalStore(approvalStore());
496 handler.setRequestFactory(requestFactory());
497 handler.setClientDetailsService(clientDetailsService);
498 this.userApprovalHandler = handler;
499 }
500 else if (tokenStore() != null) {
501 TokenStoreUserApprovalHandler userApprovalHandler = new TokenStoreUserApprovalHandler();
502 userApprovalHandler.setTokenStore(tokenStore());
503 userApprovalHandler.setClientDetailsService(clientDetailsService());
504 userApprovalHandler.setRequestFactory(requestFactory());
505 this.userApprovalHandler = userApprovalHandler;
506 }
507 else {
508 throw new IllegalStateException("Either a TokenStore or an ApprovalStore must be provided");
509 }
510 }
511 return this.userApprovalHandler;
512 }
513
514 private AuthorizationCodeServices authorizationCodeServices() {
515 if (authorizationCodeServices == null) {
516 authorizationCodeServices = new InMemoryAuthorizationCodeServices();
517 }
518 return authorizationCodeServices;
519 }
520
521 private WebResponseExceptionTranslator<OAuth2Exception> exceptionTranslator() {
522 if (exceptionTranslator != null) {
523 return exceptionTranslator;
524 }
525 exceptionTranslator = new DefaultWebResponseExceptionTranslator();
526 return exceptionTranslator;
527 }
528
529 private RedirectResolver redirectResolver() {
530 if (redirectResolver != null) {
531 return redirectResolver;
532 }
533 redirectResolver = new DefaultRedirectResolver();
534 return redirectResolver;
535 }
536
537 private OAuth2RequestFactory requestFactory() {
538 if (requestFactory != null) {
539 return requestFactory;
540 }
541 requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService());
542 return requestFactory;
543 }
544
545 private OAuth2RequestValidator requestValidator() {
546 if (requestValidator != null) {
547 return requestValidator;
548 }
549 requestValidator = new DefaultOAuth2RequestValidator();
550 return requestValidator;
551 }
552
553 private List<TokenGranter> getDefaultTokenGranters() {
554 ClientDetailsService clientDetails = clientDetailsService();
555 AuthorizationServerTokenServices tokenServices = tokenServices();
556 AuthorizationCodeServices authorizationCodeServices = authorizationCodeServices();
557 OAuth2RequestFactory requestFactory = requestFactory();
558
559 List<TokenGranter> tokenGranters = new ArrayList<TokenGranter>();
560 tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetails,
561 requestFactory));
562 tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetails, requestFactory));
563 ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetails, requestFactory);
564 tokenGranters.add(implicit);
565 tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetails, requestFactory));
566 if (authenticationManager != null) {
567 tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices,
568 clientDetails, requestFactory));
569 }
570 return tokenGranters;
571 }
572
573 private TokenGranter tokenGranter() {
574 if (tokenGranter == null) {
575 tokenGranter = new TokenGranter() {
576 private CompositeTokenGranter delegate;
577
578 @Override
579 public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
580 if (delegate == null) {
581 delegate = new CompositeTokenGranter(getDefaultTokenGranters());
582 }
583 return delegate.grant(grantType, tokenRequest);
584 }
585 };
586 }
587 return tokenGranter;
588 }
589
590 private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping() {
591 if (frameworkEndpointHandlerMapping == null) {
592 frameworkEndpointHandlerMapping = new FrameworkEndpointHandlerMapping();
593 frameworkEndpointHandlerMapping.setMappings(patternMap);
594 frameworkEndpointHandlerMapping.setPrefix(prefix);
595 frameworkEndpointHandlerMapping.setInterceptors(interceptors.toArray());
596 }
597 return frameworkEndpointHandlerMapping;
598 }
599
600 }