1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.springframework.security.oauth2.config.annotation.web.configuration;
15
16 import java.util.Collections;
17 import java.util.List;
18 import java.util.Set;
19
20 import javax.annotation.PostConstruct;
21
22 import org.springframework.beans.BeansException;
23 import org.springframework.beans.factory.BeanCreationException;
24 import org.springframework.beans.factory.BeanFactoryUtils;
25 import org.springframework.beans.factory.FactoryBean;
26 import org.springframework.beans.factory.annotation.Autowired;
27 import org.springframework.beans.factory.config.AbstractFactoryBean;
28 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
29 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
30 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
31 import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
32 import org.springframework.context.annotation.Bean;
33 import org.springframework.context.annotation.Configuration;
34 import org.springframework.context.annotation.Import;
35 import org.springframework.http.HttpMethod;
36 import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
37 import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration.TokenKeyEndpointRegistrar;
38 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
39 import org.springframework.security.oauth2.provider.ClientDetailsService;
40 import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
41 import org.springframework.security.oauth2.provider.OAuth2RequestValidator;
42 import org.springframework.security.oauth2.provider.TokenGranter;
43 import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
44 import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
45 import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint;
46 import org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint;
47 import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping;
48 import org.springframework.security.oauth2.provider.endpoint.RedirectResolver;
49 import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
50 import org.springframework.security.oauth2.provider.endpoint.TokenKeyEndpoint;
51 import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint;
52 import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint;
53 import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
54 import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
55 import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
56 import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
57 import org.springframework.stereotype.Component;
58
59
60
61
62
63 @Configuration
64 @Import(TokenKeyEndpointRegistrar.class)
65 public class AuthorizationServerEndpointsConfiguration {
66
67 private AuthorizationServerEndpointsConfigureron/web/configurers/AuthorizationServerEndpointsConfigurer.html#AuthorizationServerEndpointsConfigurer">AuthorizationServerEndpointsConfigurer endpoints = new AuthorizationServerEndpointsConfigurer();
68
69 @Autowired
70 private ClientDetailsService clientDetailsService;
71
72 @Autowired
73 private List<AuthorizationServerConfigurer> configurers = Collections.emptyList();
74
75 @PostConstruct
76 public void init() {
77 for (AuthorizationServerConfigurer configurer : configurers) {
78 try {
79 configurer.configure(endpoints);
80 } catch (Exception e) {
81 throw new IllegalStateException("Cannot configure enpdoints", e);
82 }
83 }
84 endpoints.setClientDetailsService(clientDetailsService);
85 }
86
87 @Bean
88 public AuthorizationEndpoint authorizationEndpoint() throws Exception {
89 AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint();
90 FrameworkEndpointHandlerMapping mapping = getEndpointsConfigurer().getFrameworkEndpointHandlerMapping();
91 authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access"));
92 authorizationEndpoint.setProviderExceptionHandler(exceptionTranslator());
93 authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error"));
94 authorizationEndpoint.setTokenGranter(tokenGranter());
95 authorizationEndpoint.setClientDetailsService(clientDetailsService);
96 authorizationEndpoint.setAuthorizationCodeServices(authorizationCodeServices());
97 authorizationEndpoint.setOAuth2RequestFactory(oauth2RequestFactory());
98 authorizationEndpoint.setOAuth2RequestValidator(oauth2RequestValidator());
99 authorizationEndpoint.setUserApprovalHandler(userApprovalHandler());
100 authorizationEndpoint.setRedirectResolver(redirectResolver());
101 return authorizationEndpoint;
102 }
103
104 @Bean
105 public TokenEndpoint tokenEndpoint() throws Exception {
106 TokenEndpoint tokenEndpoint = new TokenEndpoint();
107 tokenEndpoint.setClientDetailsService(clientDetailsService);
108 tokenEndpoint.setProviderExceptionHandler(exceptionTranslator());
109 tokenEndpoint.setTokenGranter(tokenGranter());
110 tokenEndpoint.setOAuth2RequestFactory(oauth2RequestFactory());
111 tokenEndpoint.setOAuth2RequestValidator(oauth2RequestValidator());
112 tokenEndpoint.setAllowedRequestMethods(allowedTokenEndpointRequestMethods());
113 return tokenEndpoint;
114 }
115
116 @Bean
117 public CheckTokenEndpoint checkTokenEndpoint() {
118 CheckTokenEndpoint endpoint = new CheckTokenEndpoint(getEndpointsConfigurer().getResourceServerTokenServices());
119 endpoint.setAccessTokenConverter(getEndpointsConfigurer().getAccessTokenConverter());
120 endpoint.setExceptionTranslator(exceptionTranslator());
121 return endpoint;
122 }
123
124 @Bean
125 public WhitelabelApprovalEndpoint whitelabelApprovalEndpoint() {
126 return new WhitelabelApprovalEndpoint();
127 }
128
129 @Bean
130 public WhitelabelErrorEndpoint whitelabelErrorEndpoint() {
131 return new WhitelabelErrorEndpoint();
132 }
133
134 @Bean
135 public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() throws Exception {
136 return getEndpointsConfigurer().getFrameworkEndpointHandlerMapping();
137 }
138
139 @Bean
140 public FactoryBean<ConsumerTokenServices> consumerTokenServices() throws Exception {
141 return new AbstractFactoryBean<ConsumerTokenServices>() {
142
143 @Override
144 public Class<?> getObjectType() {
145 return ConsumerTokenServices.class;
146 }
147
148 @Override
149 protected ConsumerTokenServices createInstance() throws Exception {
150 return getEndpointsConfigurer().getConsumerTokenServices();
151 }
152 };
153 }
154
155
156
157
158
159
160
161
162
163
164
165 @Bean
166 public FactoryBean<AuthorizationServerTokenServices> defaultAuthorizationServerTokenServices() {
167 return new AuthorizationServerTokenServicesFactoryBean(endpoints);
168 }
169
170 public AuthorizationServerEndpointsConfigurer getEndpointsConfigurer() {
171 if (!endpoints.isTokenServicesOverride()) {
172 try {
173 endpoints.tokenServices(endpoints.getDefaultAuthorizationServerTokenServices());
174 }
175 catch (Exception e) {
176 throw new BeanCreationException("Cannot create token services", e);
177 }
178 }
179 return endpoints;
180 }
181
182 private Set<HttpMethod> allowedTokenEndpointRequestMethods() {
183 return getEndpointsConfigurer().getAllowedTokenEndpointRequestMethods();
184 }
185
186 private OAuth2RequestFactory oauth2RequestFactory() throws Exception {
187 return getEndpointsConfigurer().getOAuth2RequestFactory();
188 }
189
190 private UserApprovalHandler userApprovalHandler() throws Exception {
191 return getEndpointsConfigurer().getUserApprovalHandler();
192 }
193
194 private OAuth2RequestValidator oauth2RequestValidator() throws Exception {
195 return getEndpointsConfigurer().getOAuth2RequestValidator();
196 }
197
198 private AuthorizationCodeServices authorizationCodeServices() throws Exception {
199 return getEndpointsConfigurer().getAuthorizationCodeServices();
200 }
201
202 private WebResponseExceptionTranslator<OAuth2Exception> exceptionTranslator() {
203 return getEndpointsConfigurer().getExceptionTranslator();
204 }
205
206 private RedirectResolver redirectResolver() {
207 return getEndpointsConfigurer().getRedirectResolver();
208 }
209
210 private TokenGranter tokenGranter() throws Exception {
211 return getEndpointsConfigurer().getTokenGranter();
212 }
213
214 private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) {
215 String path = mapping.getPath(page);
216 if (path.contains(":")) {
217 return path;
218 }
219 return "forward:" + path;
220 }
221
222 protected static class AuthorizationServerTokenServicesFactoryBean
223 extends AbstractFactoryBean<AuthorizationServerTokenServices> {
224
225 private AuthorizationServerEndpointsConfigurer endpoints;
226
227 protected AuthorizationServerTokenServicesFactoryBean() {
228 }
229
230 public AuthorizationServerTokenServicesFactoryBean(
231 AuthorizationServerEndpointsConfigurer endpoints) {
232 this.endpoints = endpoints;
233 }
234
235 @Override
236 public Class<?> getObjectType() {
237 return AuthorizationServerTokenServices.class;
238 }
239
240 @Override
241 protected AuthorizationServerTokenServices createInstance() throws Exception {
242 return endpoints.getDefaultAuthorizationServerTokenServices();
243 }
244 }
245
246 @Component
247 protected static class TokenKeyEndpointRegistrar implements BeanDefinitionRegistryPostProcessor {
248
249 private BeanDefinitionRegistry registry;
250
251 @Override
252 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
253 String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory,
254 JwtAccessTokenConverter.class, false, false);
255 if (names.length > 0) {
256 BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(TokenKeyEndpoint.class);
257 builder.addConstructorArgReference(names[0]);
258 registry.registerBeanDefinition(TokenKeyEndpoint.class.getName(), builder.getBeanDefinition());
259 }
260 }
261
262 @Override
263 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
264 this.registry = registry;
265 }
266
267 }
268
269 }