1 package org.springframework.security.oauth2.client.token.grant.implicit;
2
3 import java.io.IOException;
4 import java.net.URI;
5 import java.util.Collections;
6 import java.util.Iterator;
7 import java.util.List;
8
9 import org.springframework.http.HttpHeaders;
10 import org.springframework.http.client.ClientHttpResponse;
11 import org.springframework.security.access.AccessDeniedException;
12 import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
13 import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
14 import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException;
15 import org.springframework.security.oauth2.client.token.AccessTokenProvider;
16 import org.springframework.security.oauth2.client.token.AccessTokenRequest;
17 import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest;
18 import org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport;
19 import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
20 import org.springframework.security.oauth2.common.OAuth2AccessToken;
21 import org.springframework.security.oauth2.common.OAuth2RefreshToken;
22 import org.springframework.security.oauth2.common.util.OAuth2Utils;
23 import org.springframework.util.LinkedMultiValueMap;
24 import org.springframework.util.MultiValueMap;
25 import org.springframework.web.client.ResponseExtractor;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 public class ImplicitAccessTokenProvider extends OAuth2AccessTokenSupport implements AccessTokenProvider {
41
42 public boolean supportsResource(OAuth2ProtectedResourceDetails resource) {
43 return resource instanceof ImplicitResourceDetails && "implicit".equals(resource.getGrantType());
44 }
45
46 public boolean supportsRefresh(OAuth2ProtectedResourceDetails resource) {
47 return false;
48 }
49
50 public OAuth2AccessToken refreshAccessToken(OAuth2ProtectedResourceDetails resource,
51 OAuth2RefreshToken refreshToken, AccessTokenRequest request) throws UserRedirectRequiredException {
52 return null;
53 }
54
55 public OAuth2AccessToken obtainAccessToken(OAuth2ProtectedResourceDetails details, AccessTokenRequest request)
56 throws UserRedirectRequiredException, AccessDeniedException, OAuth2AccessDeniedException {
57
58 ImplicitResourceDetails resource = (ImplicitResourceDetails) details;
59 try {
60
61 OAuth2AccessToken token = retrieveToken(request,
62 resource, getParametersForTokenRequest(resource, request), getHeadersForTokenRequest(request));
63 if (token==null) {
64
65 throw new UserRedirectRequiredException(resource.getUserAuthorizationUri(), request.toSingleValueMap());
66 }
67 return token;
68 }
69 catch (UserRedirectRequiredException e) {
70
71 throw new UserRedirectRequiredException(e.getRedirectUri(), request.toSingleValueMap());
72 }
73
74 }
75
76 @Override
77 protected ResponseExtractor<OAuth2AccessToken> getResponseExtractor() {
78 return new ImplicitResponseExtractor();
79 }
80
81 private HttpHeaders getHeadersForTokenRequest(AccessTokenRequest request) {
82 HttpHeaders headers = new HttpHeaders();
83 headers.putAll(request.getHeaders());
84 if (request.getCookie() != null) {
85 headers.set("Cookie", request.getCookie());
86 }
87 return headers;
88 }
89
90 private MultiValueMap<String, String> getParametersForTokenRequest(ImplicitResourceDetails resource,
91 AccessTokenRequest request) {
92
93 MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
94 form.set("response_type", "token");
95 form.set("client_id", resource.getClientId());
96
97 if (resource.isScoped()) {
98
99 StringBuilder builder = new StringBuilder();
100 List<String> scope = resource.getScope();
101
102 if (scope != null) {
103 Iterator<String> scopeIt = scope.iterator();
104 while (scopeIt.hasNext()) {
105 builder.append(scopeIt.next());
106 if (scopeIt.hasNext()) {
107 builder.append(' ');
108 }
109 }
110 }
111
112 form.set("scope", builder.toString());
113 }
114
115 for (String key : request.keySet()) {
116 form.put(key, request.get(key));
117 }
118
119 String redirectUri = resource.getRedirectUri(request);
120 if (redirectUri == null) {
121 throw new IllegalStateException("No redirect URI available in request");
122 }
123 form.set("redirect_uri", redirectUri);
124
125 return form;
126
127 }
128
129 private final class ImplicitResponseExtractor implements ResponseExtractor<OAuth2AccessToken> {
130 public OAuth2AccessToken extractData(ClientHttpResponse response) throws IOException {
131
132 URI location = response.getHeaders().getLocation();
133 if (location == null) {
134 return null;
135 }
136 String fragment = location.getFragment();
137 OAuth2AccessToken accessToken = DefaultOAuth2AccessToken.valueOf(OAuth2Utils.extractMap(fragment));
138 if (accessToken.getValue() == null) {
139 throw new UserRedirectRequiredException(location.toString(), Collections.<String, String> emptyMap());
140 }
141
142 return accessToken;
143 }
144 }
145
146 }