1
2
3
4
5
6
7
8
9
10
11
12
13 package org.springframework.security.oauth2.provider.endpoint;
14
15 import org.springframework.http.HttpHeaders;
16 import org.springframework.http.HttpStatus;
17 import org.springframework.http.ResponseEntity;
18 import org.springframework.security.access.AccessDeniedException;
19 import org.springframework.security.authentication.InsufficientAuthenticationException;
20 import org.springframework.security.core.Authentication;
21 import org.springframework.security.core.AuthenticationException;
22 import org.springframework.security.core.GrantedAuthority;
23 import org.springframework.security.oauth2.common.OAuth2AccessToken;
24 import org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException;
25 import org.springframework.security.oauth2.common.exceptions.ClientAuthenticationException;
26 import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
27 import org.springframework.security.oauth2.common.exceptions.InvalidRequestException;
28 import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
29 import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException;
30 import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
31 import org.springframework.security.oauth2.common.exceptions.UnsupportedResponseTypeException;
32 import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException;
33 import org.springframework.security.oauth2.common.util.OAuth2Utils;
34 import org.springframework.security.oauth2.provider.AuthorizationRequest;
35 import org.springframework.security.oauth2.provider.ClientDetails;
36 import org.springframework.security.oauth2.provider.ClientRegistrationException;
37 import org.springframework.security.oauth2.provider.OAuth2Authentication;
38 import org.springframework.security.oauth2.provider.OAuth2Request;
39 import org.springframework.security.oauth2.provider.OAuth2RequestValidator;
40 import org.springframework.security.oauth2.provider.TokenRequest;
41 import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler;
42 import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
43 import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
44 import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
45 import org.springframework.security.oauth2.provider.implicit.ImplicitTokenRequest;
46 import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator;
47 import org.springframework.util.ObjectUtils;
48 import org.springframework.util.StringUtils;
49 import org.springframework.web.HttpSessionRequiredException;
50 import org.springframework.web.bind.annotation.ExceptionHandler;
51 import org.springframework.web.bind.annotation.RequestMapping;
52 import org.springframework.web.bind.annotation.RequestMethod;
53 import org.springframework.web.bind.annotation.RequestParam;
54 import org.springframework.web.bind.annotation.SessionAttributes;
55 import org.springframework.web.bind.support.DefaultSessionAttributeStore;
56 import org.springframework.web.bind.support.SessionAttributeStore;
57 import org.springframework.web.bind.support.SessionStatus;
58 import org.springframework.web.context.request.RequestContextHolder;
59 import org.springframework.web.context.request.ServletRequestAttributes;
60 import org.springframework.web.context.request.ServletWebRequest;
61 import org.springframework.web.servlet.ModelAndView;
62 import org.springframework.web.servlet.View;
63 import org.springframework.web.servlet.view.RedirectView;
64 import org.springframework.web.util.UriComponents;
65 import org.springframework.web.util.UriComponentsBuilder;
66
67 import javax.servlet.http.HttpServletResponse;
68 import java.net.URI;
69 import java.security.Principal;
70 import java.util.Collections;
71 import java.util.Date;
72 import java.util.HashMap;
73 import java.util.HashSet;
74 import java.util.LinkedHashMap;
75 import java.util.Map;
76 import java.util.Set;
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 @FrameworkEndpoint
96 @SessionAttributes({AuthorizationEndpoint.AUTHORIZATION_REQUEST_ATTR_NAME, AuthorizationEndpoint.ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME})
97 public class AuthorizationEndpoint extends AbstractEndpoint {
98 static final String AUTHORIZATION_REQUEST_ATTR_NAME = "authorizationRequest";
99
100 static final String ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME = "org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.ORIGINAL_AUTHORIZATION_REQUEST";
101
102 private AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices();
103
104 private RedirectResolver redirectResolver = new DefaultRedirectResolver();
105
106 private UserApprovalHandler userApprovalHandler = new DefaultUserApprovalHandler();
107
108 private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();
109
110 private OAuth2RequestValidator oauth2RequestValidator = new DefaultOAuth2RequestValidator();
111
112 private String userApprovalPage = "forward:/oauth/confirm_access";
113
114 private String errorPage = "forward:/oauth/error";
115
116 private Object implicitLock = new Object();
117
118 public void setSessionAttributeStore(SessionAttributeStore sessionAttributeStore) {
119 this.sessionAttributeStore = sessionAttributeStore;
120 }
121
122 public void setErrorPage(String errorPage) {
123 this.errorPage = errorPage;
124 }
125
126 @RequestMapping(value = "/oauth/authorize")
127 public ModelAndView authorize(Map<String, Object> model, @RequestParam Map<String, String> parameters,
128 SessionStatus sessionStatus, Principal principal) {
129
130
131
132
133 AuthorizationRequest authorizationRequest = getOAuth2RequestFactory().createAuthorizationRequest(parameters);
134
135 Set<String> responseTypes = authorizationRequest.getResponseTypes();
136
137 if (!responseTypes.contains("token") && !responseTypes.contains("code")) {
138 throw new UnsupportedResponseTypeException("Unsupported response types: " + responseTypes);
139 }
140
141 if (authorizationRequest.getClientId() == null) {
142 throw new InvalidClientException("A client id must be provided");
143 }
144
145 try {
146
147 if (!(principal instanceof Authentication) || !((Authentication) principal).isAuthenticated()) {
148 throw new InsufficientAuthenticationException(
149 "User must be authenticated with Spring Security before authorization can be completed.");
150 }
151
152 ClientDetails client = getClientDetailsService().loadClientByClientId(authorizationRequest.getClientId());
153
154
155
156 String redirectUriParameter = authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI);
157 String resolvedRedirect = redirectResolver.resolveRedirect(redirectUriParameter, client);
158 if (!StringUtils.hasText(resolvedRedirect)) {
159 throw new RedirectMismatchException(
160 "A redirectUri must be either supplied or preconfigured in the ClientDetails");
161 }
162 authorizationRequest.setRedirectUri(resolvedRedirect);
163
164
165
166 oauth2RequestValidator.validateScope(authorizationRequest, client);
167
168
169
170 authorizationRequest = userApprovalHandler.checkForPreApproval(authorizationRequest,
171 (Authentication) principal);
172
173 boolean approved = userApprovalHandler.isApproved(authorizationRequest, (Authentication) principal);
174 authorizationRequest.setApproved(approved);
175
176
177 if (authorizationRequest.isApproved()) {
178 if (responseTypes.contains("token")) {
179 return getImplicitGrantResponse(authorizationRequest);
180 }
181 if (responseTypes.contains("code")) {
182 return new ModelAndView(getAuthorizationCodeResponse(authorizationRequest,
183 (Authentication) principal));
184 }
185 }
186
187
188
189 model.put(AUTHORIZATION_REQUEST_ATTR_NAME, authorizationRequest);
190 model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, unmodifiableMap(authorizationRequest));
191
192 return getUserApprovalPageResponse(model, authorizationRequest, (Authentication) principal);
193
194 }
195 catch (RuntimeException e) {
196 sessionStatus.setComplete();
197 throw e;
198 }
199
200 }
201
202 Map<String, Object> unmodifiableMap(AuthorizationRequest authorizationRequest) {
203 Map<String, Object> authorizationRequestMap = new HashMap<String, Object>();
204
205 authorizationRequestMap.put(OAuth2Utils.CLIENT_ID, authorizationRequest.getClientId());
206 authorizationRequestMap.put(OAuth2Utils.STATE, authorizationRequest.getState());
207 authorizationRequestMap.put(OAuth2Utils.REDIRECT_URI, authorizationRequest.getRedirectUri());
208 if (authorizationRequest.getResponseTypes() != null) {
209 authorizationRequestMap.put(OAuth2Utils.RESPONSE_TYPE,
210 Collections.unmodifiableSet(new HashSet<String>(authorizationRequest.getResponseTypes())));
211 }
212 if (authorizationRequest.getScope() != null) {
213 authorizationRequestMap.put(OAuth2Utils.SCOPE,
214 Collections.unmodifiableSet(new HashSet<String>(authorizationRequest.getScope())));
215 }
216 authorizationRequestMap.put("approved", authorizationRequest.isApproved());
217 if (authorizationRequest.getResourceIds() != null) {
218 authorizationRequestMap.put("resourceIds",
219 Collections.unmodifiableSet(new HashSet<String>(authorizationRequest.getResourceIds())));
220 }
221 if (authorizationRequest.getAuthorities() != null) {
222 authorizationRequestMap.put("authorities",
223 Collections.unmodifiableSet(new HashSet<GrantedAuthority>(authorizationRequest.getAuthorities())));
224 }
225
226 return Collections.unmodifiableMap(authorizationRequestMap);
227 }
228
229 @RequestMapping(value = "/oauth/authorize", method = RequestMethod.POST, params = OAuth2Utils.USER_OAUTH_APPROVAL)
230 public View approveOrDeny(@RequestParam Map<String, String> approvalParameters, Map<String, ?> model,
231 SessionStatus sessionStatus, Principal principal) {
232
233 if (!(principal instanceof Authentication)) {
234 sessionStatus.setComplete();
235 throw new InsufficientAuthenticationException(
236 "User must be authenticated with Spring Security before authorizing an access token.");
237 }
238
239 AuthorizationRequest authorizationRequest = (AuthorizationRequest) model.get(AUTHORIZATION_REQUEST_ATTR_NAME);
240
241 if (authorizationRequest == null) {
242 sessionStatus.setComplete();
243 throw new InvalidRequestException("Cannot approve uninitialized authorization request.");
244 }
245
246
247 @SuppressWarnings("unchecked")
248 Map<String, Object> originalAuthorizationRequest = (Map<String, Object>) model.get(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME);
249 if (isAuthorizationRequestModified(authorizationRequest, originalAuthorizationRequest)) {
250 throw new InvalidRequestException("Changes were detected from the original authorization request.");
251 }
252
253 try {
254 Set<String> responseTypes = authorizationRequest.getResponseTypes();
255
256 authorizationRequest.setApprovalParameters(approvalParameters);
257 authorizationRequest = userApprovalHandler.updateAfterApproval(authorizationRequest,
258 (Authentication) principal);
259 boolean approved = userApprovalHandler.isApproved(authorizationRequest, (Authentication) principal);
260 authorizationRequest.setApproved(approved);
261
262 if (authorizationRequest.getRedirectUri() == null) {
263 sessionStatus.setComplete();
264 throw new InvalidRequestException("Cannot approve request when no redirect URI is provided.");
265 }
266
267 if (!authorizationRequest.isApproved()) {
268 RedirectView redirectView = new RedirectView(getUnsuccessfulRedirect(authorizationRequest,
269 new UserDeniedAuthorizationException("User denied access"), responseTypes.contains("token")),
270 false, true, false);
271 redirectView.setStatusCode(HttpStatus.SEE_OTHER);
272 return redirectView;
273 }
274
275 if (responseTypes.contains("token")) {
276 return getImplicitGrantResponse(authorizationRequest).getView();
277 }
278
279 return getAuthorizationCodeResponse(authorizationRequest, (Authentication) principal);
280 }
281 finally {
282 sessionStatus.setComplete();
283 }
284
285 }
286
287 private boolean isAuthorizationRequestModified(
288 AuthorizationRequest authorizationRequest, Map<String, Object> originalAuthorizationRequest) {
289 if (!ObjectUtils.nullSafeEquals(
290 authorizationRequest.getClientId(),
291 originalAuthorizationRequest.get(OAuth2Utils.CLIENT_ID))) {
292 return true;
293 }
294 if (!ObjectUtils.nullSafeEquals(
295 authorizationRequest.getState(),
296 originalAuthorizationRequest.get(OAuth2Utils.STATE))) {
297 return true;
298 }
299 if (!ObjectUtils.nullSafeEquals(
300 authorizationRequest.getRedirectUri(),
301 originalAuthorizationRequest.get(OAuth2Utils.REDIRECT_URI))) {
302 return true;
303 }
304 if (!ObjectUtils.nullSafeEquals(
305 authorizationRequest.getResponseTypes(),
306 originalAuthorizationRequest.get(OAuth2Utils.RESPONSE_TYPE))) {
307 return true;
308 }
309 if (!ObjectUtils.nullSafeEquals(
310 authorizationRequest.getScope(),
311 originalAuthorizationRequest.get(OAuth2Utils.SCOPE))) {
312 return true;
313 }
314 if (!ObjectUtils.nullSafeEquals(
315 authorizationRequest.isApproved(),
316 originalAuthorizationRequest.get("approved"))) {
317 return true;
318 }
319 if (!ObjectUtils.nullSafeEquals(
320 authorizationRequest.getResourceIds(),
321 originalAuthorizationRequest.get("resourceIds"))) {
322 return true;
323 }
324 if (!ObjectUtils.nullSafeEquals(
325 authorizationRequest.getAuthorities(),
326 originalAuthorizationRequest.get("authorities"))) {
327 return true;
328 }
329
330 return false;
331 }
332
333
334 private ModelAndView getUserApprovalPageResponse(Map<String, Object> model,
335 AuthorizationRequest authorizationRequest, Authentication principal) {
336 if (logger.isDebugEnabled()) {
337 logger.debug("Loading user approval page: " + userApprovalPage);
338 }
339 model.putAll(userApprovalHandler.getUserApprovalRequest(authorizationRequest, principal));
340 return new ModelAndView(userApprovalPage, model);
341 }
342
343
344 private ModelAndView getImplicitGrantResponse(AuthorizationRequest authorizationRequest) {
345 try {
346 TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(authorizationRequest, "implicit");
347 OAuth2Request storedOAuth2Request = getOAuth2RequestFactory().createOAuth2Request(authorizationRequest);
348 OAuth2AccessToken accessToken = getAccessTokenForImplicitGrant(tokenRequest, storedOAuth2Request);
349 if (accessToken == null) {
350 throw new UnsupportedResponseTypeException("Unsupported response type: token");
351 }
352 setCacheControlHeaders();
353 RedirectView redirectView = new RedirectView(appendAccessToken(authorizationRequest, accessToken), false, true,
354 false);
355 redirectView.setStatusCode(HttpStatus.SEE_OTHER);
356 return new ModelAndView(redirectView);
357 }
358 catch (OAuth2Exception e) {
359 RedirectView redirectView = new RedirectView(getUnsuccessfulRedirect(authorizationRequest, e, true), false,
360 true, false);
361 redirectView.setStatusCode(HttpStatus.SEE_OTHER);
362 return new ModelAndView(redirectView);
363 }
364 }
365
366 private OAuth2AccessToken getAccessTokenForImplicitGrant(TokenRequest tokenRequest,
367 OAuth2Request storedOAuth2Request) {
368 OAuth2AccessToken accessToken = null;
369
370
371 synchronized (this.implicitLock) {
372 accessToken = getTokenGranter().grant("implicit",
373 new ImplicitTokenRequest(tokenRequest, storedOAuth2Request));
374 }
375 return accessToken;
376 }
377
378 private View getAuthorizationCodeResponse(AuthorizationRequest authorizationRequest, Authentication authUser) {
379 try {
380 RedirectView redirectView = new RedirectView(getSuccessfulRedirect(authorizationRequest,
381 generateCode(authorizationRequest, authUser)), false, true, false);
382 redirectView.setStatusCode(HttpStatus.SEE_OTHER);
383 return redirectView;
384 }
385 catch (OAuth2Exception e) {
386 RedirectView redirectView = new RedirectView(getUnsuccessfulRedirect(authorizationRequest, e, false), false, true, false);
387 redirectView.setStatusCode(HttpStatus.SEE_OTHER);
388 return redirectView;
389 }
390 }
391
392 private String appendAccessToken(AuthorizationRequest authorizationRequest, OAuth2AccessToken accessToken) {
393
394 Map<String, Object> vars = new LinkedHashMap<String, Object>();
395 Map<String, String> keys = new HashMap<String, String>();
396
397 if (accessToken == null) {
398 throw new InvalidRequestException("An implicit grant could not be made");
399 }
400
401 vars.put("access_token", accessToken.getValue());
402 vars.put("token_type", accessToken.getTokenType());
403 String state = authorizationRequest.getState();
404
405 if (state != null) {
406 vars.put("state", state);
407 }
408 Date expiration = accessToken.getExpiration();
409 if (expiration != null) {
410 long expires_in = (expiration.getTime() - System.currentTimeMillis()) / 1000;
411 vars.put("expires_in", expires_in);
412 }
413 String originalScope = authorizationRequest.getRequestParameters().get(OAuth2Utils.SCOPE);
414 if (originalScope == null || !OAuth2Utils.parseParameterList(originalScope).equals(accessToken.getScope())) {
415 vars.put("scope", OAuth2Utils.formatParameterList(accessToken.getScope()));
416 }
417 Map<String, Object> additionalInformation = accessToken.getAdditionalInformation();
418 for (String key : additionalInformation.keySet()) {
419 Object value = additionalInformation.get(key);
420 if (value != null) {
421 keys.put("extra_" + key, key);
422 vars.put("extra_" + key, value);
423 }
424 }
425
426 return append(authorizationRequest.getRedirectUri(), vars, keys, true);
427 }
428
429 private String generateCode(AuthorizationRequest authorizationRequest, Authentication authentication)
430 throws AuthenticationException {
431
432 try {
433
434 OAuth2Request storedOAuth2Request = getOAuth2RequestFactory().createOAuth2Request(authorizationRequest);
435
436 OAuth2Authentication combinedAuth = new OAuth2Authentication(storedOAuth2Request, authentication);
437 String code = authorizationCodeServices.createAuthorizationCode(combinedAuth);
438
439 return code;
440
441 }
442 catch (OAuth2Exception e) {
443
444 if (authorizationRequest.getState() != null) {
445 e.addAdditionalInformation("state", authorizationRequest.getState());
446 }
447
448 throw e;
449
450 }
451 }
452
453 private String getSuccessfulRedirect(AuthorizationRequest authorizationRequest, String authorizationCode) {
454
455 if (authorizationCode == null) {
456 throw new IllegalStateException("No authorization code found in the current request scope.");
457 }
458
459 Map<String, String> query = new LinkedHashMap<String, String>();
460 query.put("code", authorizationCode);
461
462 String state = authorizationRequest.getState();
463 if (state != null) {
464 query.put("state", state);
465 }
466
467 return append(authorizationRequest.getRedirectUri(), query, false);
468 }
469
470 private String getUnsuccessfulRedirect(AuthorizationRequest authorizationRequest, OAuth2Exception failure,
471 boolean fragment) {
472
473 if (authorizationRequest == null || authorizationRequest.getRedirectUri() == null) {
474
475 throw new UnapprovedClientAuthenticationException("Authorization failure, and no redirect URI.", failure);
476 }
477
478 Map<String, String> query = new LinkedHashMap<String, String>();
479
480 query.put("error", failure.getOAuth2ErrorCode());
481 query.put("error_description", failure.getMessage());
482
483 if (authorizationRequest.getState() != null) {
484 query.put("state", authorizationRequest.getState());
485 }
486
487 if (failure.getAdditionalInformation() != null) {
488 for (Map.Entry<String, String> additionalInfo : failure.getAdditionalInformation().entrySet()) {
489 query.put(additionalInfo.getKey(), additionalInfo.getValue());
490 }
491 }
492
493 return append(authorizationRequest.getRedirectUri(), query, fragment);
494
495 }
496
497 private String append(String base, Map<String, ?> query, boolean fragment) {
498 return append(base, query, null, fragment);
499 }
500
501 private String append(String base, Map<String, ?> query, Map<String, String> keys, boolean fragment) {
502
503 UriComponentsBuilder template = UriComponentsBuilder.newInstance();
504 UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(base);
505 URI redirectUri;
506 try {
507
508 redirectUri = builder.build(true).toUri();
509 }
510 catch (Exception e) {
511
512 redirectUri = builder.build().toUri();
513 builder = UriComponentsBuilder.fromUri(redirectUri);
514 }
515 template.scheme(redirectUri.getScheme()).port(redirectUri.getPort()).host(redirectUri.getHost())
516 .userInfo(redirectUri.getUserInfo()).path(redirectUri.getPath());
517
518 if (fragment) {
519 StringBuilder values = new StringBuilder();
520 if (redirectUri.getFragment() != null) {
521 String append = redirectUri.getFragment();
522 values.append(append);
523 }
524 for (String key : query.keySet()) {
525 if (values.length() > 0) {
526 values.append("&");
527 }
528 String name = key;
529 if (keys != null && keys.containsKey(key)) {
530 name = keys.get(key);
531 }
532 values.append(name + "={" + key + "}");
533 }
534 if (values.length() > 0) {
535 template.fragment(values.toString());
536 }
537 UriComponents encoded = template.build().expand(query).encode();
538 builder.fragment(encoded.getFragment());
539 }
540 else {
541 for (String key : query.keySet()) {
542 String name = key;
543 if (keys != null && keys.containsKey(key)) {
544 name = keys.get(key);
545 }
546 template.queryParam(name, "{" + key + "}");
547 }
548 template.fragment(redirectUri.getFragment());
549 UriComponents encoded = template.build().expand(query).encode();
550 builder.query(encoded.getQuery());
551 }
552
553 return builder.build().toUriString();
554
555 }
556
557 public void setUserApprovalPage(String userApprovalPage) {
558 this.userApprovalPage = userApprovalPage;
559 }
560
561 public void setAuthorizationCodeServices(AuthorizationCodeServices authorizationCodeServices) {
562 this.authorizationCodeServices = authorizationCodeServices;
563 }
564
565 public void setRedirectResolver(RedirectResolver redirectResolver) {
566 this.redirectResolver = redirectResolver;
567 }
568
569 public void setUserApprovalHandler(UserApprovalHandler userApprovalHandler) {
570 this.userApprovalHandler = userApprovalHandler;
571 }
572
573 public void setOAuth2RequestValidator(OAuth2RequestValidator oauth2RequestValidator) {
574 this.oauth2RequestValidator = oauth2RequestValidator;
575 }
576
577 @SuppressWarnings("deprecation")
578 public void setImplicitGrantService(
579 org.springframework.security.oauth2.provider.implicit.ImplicitGrantService implicitGrantService) {
580 }
581
582 @ExceptionHandler(ClientRegistrationException.class)
583 public ModelAndView handleClientRegistrationException(Exception e, ServletWebRequest webRequest) throws Exception {
584 logger.info("Handling ClientRegistrationException error: " + e.getMessage());
585 return handleException(new BadClientCredentialsException(), webRequest);
586 }
587
588 @ExceptionHandler(OAuth2Exception.class)
589 public ModelAndView handleOAuth2Exception(OAuth2Exception e, ServletWebRequest webRequest) throws Exception {
590 logger.info("Handling OAuth2 error: " + e.getSummary());
591 return handleException(e, webRequest);
592 }
593
594 @ExceptionHandler(HttpSessionRequiredException.class)
595 public ModelAndView handleHttpSessionRequiredException(HttpSessionRequiredException e, ServletWebRequest webRequest)
596 throws Exception {
597 logger.info("Handling Session required error: " + e.getMessage());
598 return handleException(new AccessDeniedException("Could not obtain authorization request from session", e),
599 webRequest);
600 }
601
602 private ModelAndView handleException(Exception e, ServletWebRequest webRequest) throws Exception {
603
604 ResponseEntity<OAuth2Exception> translate = getExceptionTranslator().translate(e);
605 webRequest.getResponse().setStatus(translate.getStatusCode().value());
606
607 if (e instanceof ClientAuthenticationException || e instanceof RedirectMismatchException) {
608 return new ModelAndView(errorPage, Collections.singletonMap("error", translate.getBody()));
609 }
610
611 AuthorizationRequest authorizationRequest = null;
612 try {
613 authorizationRequest = getAuthorizationRequestForError(webRequest);
614 String requestedRedirectParam = authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI);
615 String requestedRedirect = redirectResolver.resolveRedirect(requestedRedirectParam,
616 getClientDetailsService().loadClientByClientId(authorizationRequest.getClientId()));
617 authorizationRequest.setRedirectUri(requestedRedirect);
618 String redirect = getUnsuccessfulRedirect(authorizationRequest, translate.getBody(), authorizationRequest
619 .getResponseTypes().contains("token"));
620 RedirectView redirectView = new RedirectView(redirect, false, true, false);
621 redirectView.setStatusCode(HttpStatus.SEE_OTHER);
622 return new ModelAndView(redirectView);
623 }
624 catch (OAuth2Exception ex) {
625
626
627
628 return new ModelAndView(errorPage, Collections.singletonMap("error", translate.getBody()));
629 }
630
631 }
632
633 private AuthorizationRequest getAuthorizationRequestForError(ServletWebRequest webRequest) {
634
635
636 AuthorizationRequest authorizationRequest = (AuthorizationRequest) sessionAttributeStore.retrieveAttribute(
637 webRequest, AUTHORIZATION_REQUEST_ATTR_NAME);
638 if (authorizationRequest != null) {
639 return authorizationRequest;
640 }
641
642 Map<String, String> parameters = new HashMap<String, String>();
643 Map<String, String[]> map = webRequest.getParameterMap();
644 for (String key : map.keySet()) {
645 String[] values = map.get(key);
646 if (values != null && values.length > 0) {
647 parameters.put(key, values[0]);
648 }
649 }
650
651 try {
652 return getOAuth2RequestFactory().createAuthorizationRequest(parameters);
653 }
654 catch (Exception e) {
655 return getDefaultOAuth2RequestFactory().createAuthorizationRequest(parameters);
656 }
657
658 }
659
660 private void setCacheControlHeaders() {
661 ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
662 if (servletRequestAttributes != null) {
663 HttpServletResponse servletResponse = servletRequestAttributes.getResponse();
664 servletResponse.setHeader(HttpHeaders.CACHE_CONTROL, "no-store");
665 servletResponse.setHeader(HttpHeaders.PRAGMA, "no-cache");
666 }
667 }
668 }