1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.springframework.security.oauth2.config.xml;
15
16 import org.springframework.beans.BeanMetadataElement;
17 import org.springframework.beans.factory.config.RuntimeBeanReference;
18 import org.springframework.beans.factory.config.TypedStringValue;
19 import org.springframework.beans.factory.support.AbstractBeanDefinition;
20 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
21 import org.springframework.beans.factory.support.ManagedList;
22 import org.springframework.beans.factory.support.ManagedMap;
23 import org.springframework.beans.factory.xml.ParserContext;
24 import org.springframework.security.config.BeanIds;
25 import org.springframework.security.oauth2.provider.CompositeTokenGranter;
26 import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler;
27 import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter;
28 import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter;
29 import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
30 import org.springframework.security.oauth2.provider.endpoint.*;
31 import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter;
32 import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
33 import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter;
34 import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
35 import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator;
36 import org.springframework.util.StringUtils;
37 import org.springframework.util.xml.DomUtils;
38 import org.w3c.dom.Element;
39
40 import java.util.List;
41
42
43
44
45
46
47
48 public class AuthorizationServerBeanDefinitionParser
49 extends ProviderBeanDefinitionParser {
50
51 @Override
52 protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element,
53 ParserContext parserContext, String tokenServicesRef, String serializerRef) {
54
55 String clientDetailsRef = element.getAttribute("client-details-service-ref");
56 String oAuth2RequestFactoryRef = element
57 .getAttribute("authorization-request-manager-ref");
58 String tokenEndpointUrl = element.getAttribute("token-endpoint-url");
59 String checkTokenUrl = element.getAttribute("check-token-endpoint-url");
60 String enableCheckToken = element.getAttribute("check-token-enabled");
61 String authorizationEndpointUrl = element
62 .getAttribute("authorization-endpoint-url");
63 String tokenGranterRef = element.getAttribute("token-granter-ref");
64 String redirectStrategyRef = element.getAttribute("redirect-strategy-ref");
65 String userApprovalHandlerRef = element.getAttribute("user-approval-handler-ref");
66
67 String approvalPage = element.getAttribute("user-approval-page");
68 String errorPage = element.getAttribute("error-page");
69 String approvalParameter = element.getAttribute("approval-parameter-name");
70 String redirectResolverRef = element.getAttribute("redirect-resolver-ref");
71
72 String oAuth2RequestValidatorRef = element.getAttribute("request-validator-ref");
73
74
75 BeanDefinitionBuilder authorizationEndpointBean = BeanDefinitionBuilder
76 .rootBeanDefinition(AuthorizationEndpoint.class);
77
78 if (!StringUtils.hasText(clientDetailsRef)) {
79 parserContext.getReaderContext()
80 .error("ClientDetailsService must be provided", element);
81 return null;
82 }
83
84 if (!StringUtils.hasText(oAuth2RequestValidatorRef)) {
85 oAuth2RequestValidatorRef = "defaultOAuth2RequestValidator";
86 BeanDefinitionBuilder oAuth2RequestValidator = BeanDefinitionBuilder
87 .rootBeanDefinition(DefaultOAuth2RequestValidator.class);
88 parserContext.getRegistry().registerBeanDefinition(oAuth2RequestValidatorRef,
89 oAuth2RequestValidator.getBeanDefinition());
90 }
91 authorizationEndpointBean.addPropertyReference("oAuth2RequestValidator",
92 oAuth2RequestValidatorRef);
93
94 if (!StringUtils.hasText(oAuth2RequestFactoryRef)) {
95 oAuth2RequestFactoryRef = "oAuth2AuthorizationRequestManager";
96 BeanDefinitionBuilder oAuth2RequestManager = BeanDefinitionBuilder
97 .rootBeanDefinition(DefaultOAuth2RequestFactory.class);
98 oAuth2RequestManager.addConstructorArgReference(clientDetailsRef);
99 parserContext.getRegistry().registerBeanDefinition(oAuth2RequestFactoryRef,
100 oAuth2RequestManager.getBeanDefinition());
101 }
102
103 ManagedList<BeanMetadataElement> tokenGranters = null;
104 if (!StringUtils.hasText(tokenGranterRef)) {
105 tokenGranterRef = "oauth2TokenGranter";
106 BeanDefinitionBuilder tokenGranterBean = BeanDefinitionBuilder
107 .rootBeanDefinition(CompositeTokenGranter.class);
108 parserContext.getRegistry().registerBeanDefinition(tokenGranterRef,
109 tokenGranterBean.getBeanDefinition());
110 tokenGranters = new ManagedList<BeanMetadataElement>();
111 tokenGranterBean.addConstructorArgValue(tokenGranters);
112 }
113 authorizationEndpointBean.addPropertyReference("tokenGranter", tokenGranterRef);
114
115 boolean registerAuthorizationEndpoint = false;
116
117 Element authorizationCodeElement = DomUtils.getChildElementByTagName(element,
118 "authorization-code");
119
120 if (authorizationCodeElement != null && !"true"
121 .equalsIgnoreCase(authorizationCodeElement.getAttribute("disabled"))) {
122
123 String authorizationCodeServices = authorizationCodeElement
124 .getAttribute("authorization-code-services-ref");
125 String clientTokenCacheRef = authorizationCodeElement
126 .getAttribute("client-token-cache-ref");
127
128 BeanDefinitionBuilder authorizationCodeTokenGranterBean = BeanDefinitionBuilder
129 .rootBeanDefinition(AuthorizationCodeTokenGranter.class);
130
131 if (StringUtils.hasText(tokenServicesRef)) {
132 authorizationCodeTokenGranterBean
133 .addConstructorArgReference(tokenServicesRef);
134 }
135
136 if (!StringUtils.hasText(authorizationCodeServices)) {
137 authorizationCodeServices = "oauth2AuthorizationCodeServices";
138 BeanDefinitionBuilder authorizationCodeServicesBean = BeanDefinitionBuilder
139 .rootBeanDefinition(InMemoryAuthorizationCodeServices.class);
140 parserContext.getRegistry().registerBeanDefinition(
141 authorizationCodeServices,
142 authorizationCodeServicesBean.getBeanDefinition());
143 }
144
145 authorizationEndpointBean.addPropertyReference("authorizationCodeServices",
146 authorizationCodeServices);
147 authorizationCodeTokenGranterBean
148 .addConstructorArgReference(authorizationCodeServices);
149 authorizationCodeTokenGranterBean
150 .addConstructorArgReference(clientDetailsRef);
151 authorizationCodeTokenGranterBean
152 .addConstructorArgReference(oAuth2RequestFactoryRef);
153
154 if (StringUtils.hasText(clientTokenCacheRef)) {
155 authorizationEndpointBean.addPropertyReference("clientTokenCache",
156 clientTokenCacheRef);
157 }
158 if (StringUtils.hasText(oAuth2RequestFactoryRef)) {
159 authorizationEndpointBean.addPropertyReference("oAuth2RequestFactory",
160 oAuth2RequestFactoryRef);
161 }
162
163 if (tokenGranters != null) {
164 tokenGranters.add(authorizationCodeTokenGranterBean.getBeanDefinition());
165 }
166
167 registerAuthorizationEndpoint = true;
168 }
169
170 if (tokenGranters != null) {
171 Element refreshTokenElement = DomUtils.getChildElementByTagName(element,
172 "refresh-token");
173
174 if (refreshTokenElement != null && !"true"
175 .equalsIgnoreCase(refreshTokenElement.getAttribute("disabled"))) {
176 BeanDefinitionBuilder refreshTokenGranterBean = BeanDefinitionBuilder
177 .rootBeanDefinition(RefreshTokenGranter.class);
178 refreshTokenGranterBean.addConstructorArgReference(tokenServicesRef);
179 refreshTokenGranterBean.addConstructorArgReference(clientDetailsRef);
180 refreshTokenGranterBean
181 .addConstructorArgReference(oAuth2RequestFactoryRef);
182 tokenGranters.add(refreshTokenGranterBean.getBeanDefinition());
183 }
184 Element implicitElement = DomUtils.getChildElementByTagName(element,
185 "implicit");
186 if (implicitElement != null && !"true"
187 .equalsIgnoreCase(implicitElement.getAttribute("disabled"))) {
188 BeanDefinitionBuilder implicitGranterBean = BeanDefinitionBuilder
189 .rootBeanDefinition(ImplicitTokenGranter.class);
190 implicitGranterBean.addConstructorArgReference(tokenServicesRef);
191 implicitGranterBean.addConstructorArgReference(clientDetailsRef);
192 implicitGranterBean.addConstructorArgReference(oAuth2RequestFactoryRef);
193 tokenGranters.add(implicitGranterBean.getBeanDefinition());
194 registerAuthorizationEndpoint = true;
195 }
196 Element clientCredentialsElement = DomUtils.getChildElementByTagName(element,
197 "client-credentials");
198 if (clientCredentialsElement != null && !"true".equalsIgnoreCase(
199 clientCredentialsElement.getAttribute("disabled"))) {
200 BeanDefinitionBuilder clientCredentialsGranterBean = BeanDefinitionBuilder
201 .rootBeanDefinition(ClientCredentialsTokenGranter.class);
202 clientCredentialsGranterBean.addConstructorArgReference(tokenServicesRef);
203 clientCredentialsGranterBean.addConstructorArgReference(clientDetailsRef);
204 clientCredentialsGranterBean
205 .addConstructorArgReference(oAuth2RequestFactoryRef);
206 tokenGranters.add(clientCredentialsGranterBean.getBeanDefinition());
207 }
208 Element clientPasswordElement = DomUtils.getChildElementByTagName(element,
209 "password");
210 if (clientPasswordElement != null && !"true"
211 .equalsIgnoreCase(clientPasswordElement.getAttribute("disabled"))) {
212 BeanDefinitionBuilder clientPasswordTokenGranter = BeanDefinitionBuilder
213 .rootBeanDefinition(ResourceOwnerPasswordTokenGranter.class);
214 String authenticationManagerRef = clientPasswordElement
215 .getAttribute("authentication-manager-ref");
216 if (!StringUtils.hasText(authenticationManagerRef)) {
217 authenticationManagerRef = BeanIds.AUTHENTICATION_MANAGER;
218 }
219 clientPasswordTokenGranter
220 .addConstructorArgReference(authenticationManagerRef);
221 clientPasswordTokenGranter.addConstructorArgReference(tokenServicesRef);
222 clientPasswordTokenGranter.addConstructorArgReference(clientDetailsRef);
223 clientPasswordTokenGranter
224 .addConstructorArgReference(oAuth2RequestFactoryRef);
225 tokenGranters.add(clientPasswordTokenGranter.getBeanDefinition());
226 }
227 List<Element> customGrantElements = DomUtils
228 .getChildElementsByTagName(element, "custom-grant");
229 for (Element customGrantElement : customGrantElements) {
230 if (!"true"
231 .equalsIgnoreCase(customGrantElement.getAttribute("disabled"))) {
232 String customGranterRef = customGrantElement
233 .getAttribute("token-granter-ref");
234 tokenGranters.add(new RuntimeBeanReference(customGranterRef));
235 }
236 }
237 }
238
239 if (registerAuthorizationEndpoint) {
240
241 BeanDefinitionBuilder approvalEndpointBean = BeanDefinitionBuilder
242 .rootBeanDefinition(WhitelabelApprovalEndpoint.class);
243 parserContext.getRegistry().registerBeanDefinition("oauth2ApprovalEndpoint",
244 approvalEndpointBean.getBeanDefinition());
245
246 if (!StringUtils.hasText(clientDetailsRef)) {
247 parserContext.getReaderContext()
248 .error("A client details service is mandatory", element);
249 }
250
251 if (StringUtils.hasText(redirectStrategyRef)) {
252 authorizationEndpointBean.addPropertyReference("redirectStrategy",
253 redirectStrategyRef);
254 }
255
256 if (StringUtils.hasText(userApprovalHandlerRef)) {
257 authorizationEndpointBean.addPropertyReference("userApprovalHandler",
258 userApprovalHandlerRef);
259 }
260
261 authorizationEndpointBean.addPropertyReference("clientDetailsService",
262 clientDetailsRef);
263 if (StringUtils.hasText(redirectResolverRef)) {
264 authorizationEndpointBean.addPropertyReference("redirectResolver",
265 redirectResolverRef);
266 }
267 if (StringUtils.hasText(approvalPage)) {
268 authorizationEndpointBean.addPropertyValue("userApprovalPage",
269 approvalPage);
270 }
271 if (StringUtils.hasText(errorPage)) {
272 authorizationEndpointBean.addPropertyValue("errorPage", errorPage);
273 }
274
275 parserContext.getRegistry().registerBeanDefinition(
276 "oauth2AuthorizationEndpoint",
277 authorizationEndpointBean.getBeanDefinition());
278 }
279
280
281 BeanDefinitionBuilder tokenEndpointBean = BeanDefinitionBuilder
282 .rootBeanDefinition(TokenEndpoint.class);
283 tokenEndpointBean.addPropertyReference("clientDetailsService", clientDetailsRef);
284 tokenEndpointBean.addPropertyReference("tokenGranter", tokenGranterRef);
285 authorizationEndpointBean.addPropertyReference("oAuth2RequestValidator",
286 oAuth2RequestValidatorRef);
287 parserContext.getRegistry().registerBeanDefinition("oauth2TokenEndpoint",
288 tokenEndpointBean.getBeanDefinition());
289 if (StringUtils.hasText(oAuth2RequestFactoryRef)) {
290 tokenEndpointBean.addPropertyReference("oAuth2RequestFactory",
291 oAuth2RequestFactoryRef);
292 }
293 if (StringUtils.hasText(oAuth2RequestValidatorRef)) {
294 tokenEndpointBean.addPropertyReference("oAuth2RequestValidator",
295 oAuth2RequestValidatorRef);
296 }
297
298
299 BeanDefinitionBuilder handlerMappingBean = BeanDefinitionBuilder
300 .rootBeanDefinition(FrameworkEndpointHandlerMapping.class);
301 ManagedMap<String, TypedStringValue> mappings = new ManagedMap<String, TypedStringValue>();
302 if (StringUtils.hasText(tokenEndpointUrl)
303 || StringUtils.hasText(authorizationEndpointUrl)) {
304 if (StringUtils.hasText(tokenEndpointUrl)) {
305 mappings.put("/oauth/token",
306 new TypedStringValue(tokenEndpointUrl, String.class));
307 }
308 if (StringUtils.hasText(authorizationEndpointUrl)) {
309 mappings.put("/oauth/authorize",
310 new TypedStringValue(authorizationEndpointUrl, String.class));
311 }
312 if (StringUtils.hasText(approvalPage)) {
313 mappings.put("/oauth/confirm_access",
314 new TypedStringValue(approvalPage, String.class));
315 }
316 }
317 if (StringUtils.hasText(enableCheckToken) && enableCheckToken.equals("true")) {
318
319 BeanDefinitionBuilder checkTokenEndpointBean = BeanDefinitionBuilder
320 .rootBeanDefinition(CheckTokenEndpoint.class);
321 checkTokenEndpointBean.addConstructorArgReference(tokenServicesRef);
322 parserContext.getRegistry().registerBeanDefinition("oauth2CheckTokenEndpoint",
323 checkTokenEndpointBean.getBeanDefinition());
324
325 if (StringUtils.hasText(checkTokenUrl)) {
326 mappings.put("/oauth/check_token",
327 new TypedStringValue(checkTokenUrl, String.class));
328 }
329 }
330 if (!mappings.isEmpty()) {
331 handlerMappingBean.addPropertyValue("mappings", mappings);
332 }
333
334 if (StringUtils.hasText(approvalParameter) && registerAuthorizationEndpoint) {
335 if (!StringUtils.hasText(userApprovalHandlerRef)) {
336 BeanDefinitionBuilder userApprovalHandler = BeanDefinitionBuilder
337 .rootBeanDefinition(DefaultUserApprovalHandler.class);
338 userApprovalHandler.addPropertyValue("approvalParameter",
339 new TypedStringValue(approvalParameter, String.class));
340 authorizationEndpointBean.addPropertyValue("userApprovalHandler",
341 userApprovalHandler.getBeanDefinition());
342 }
343 handlerMappingBean.addPropertyValue("approvalParameter", approvalParameter);
344 }
345
346 parserContext.getRegistry().registerBeanDefinition("oauth2HandlerMapping",
347 handlerMappingBean.getBeanDefinition());
348
349
350 return null;
351
352 }
353
354 }