1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.springframework.security.oauth2.provider.token;
15
16 import java.util.Date;
17 import java.util.Set;
18 import java.util.UUID;
19
20 import org.springframework.beans.factory.InitializingBean;
21 import org.springframework.security.authentication.AuthenticationManager;
22 import org.springframework.security.core.Authentication;
23 import org.springframework.security.core.AuthenticationException;
24 import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken;
25 import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
26 import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken;
27 import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;
28 import org.springframework.security.oauth2.common.OAuth2AccessToken;
29 import org.springframework.security.oauth2.common.OAuth2RefreshToken;
30 import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
31 import org.springframework.security.oauth2.common.exceptions.InvalidScopeException;
32 import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
33 import org.springframework.security.oauth2.provider.ClientDetails;
34 import org.springframework.security.oauth2.provider.ClientDetailsService;
35 import org.springframework.security.oauth2.provider.ClientRegistrationException;
36 import org.springframework.security.oauth2.provider.OAuth2Authentication;
37 import org.springframework.security.oauth2.provider.OAuth2Request;
38 import org.springframework.security.oauth2.provider.TokenRequest;
39 import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
40 import org.springframework.transaction.annotation.Transactional;
41 import org.springframework.util.Assert;
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class DefaultTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices,
56 ConsumerTokenServices, InitializingBean {
57
58 private int refreshTokenValiditySeconds = 60 * 60 * 24 * 30;
59
60 private int accessTokenValiditySeconds = 60 * 60 * 12;
61
62 private boolean supportRefreshToken = false;
63
64 private boolean reuseRefreshToken = true;
65
66 private TokenStore tokenStore;
67
68 private ClientDetailsService clientDetailsService;
69
70 private TokenEnhancer accessTokenEnhancer;
71
72 private AuthenticationManager authenticationManager;
73
74
75
76
77 public void afterPropertiesSet() throws Exception {
78 Assert.notNull(tokenStore, "tokenStore must be set");
79 }
80
81 @Transactional
82 public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {
83
84 OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication);
85 OAuth2RefreshToken refreshToken = null;
86 if (existingAccessToken != null) {
87 if (existingAccessToken.isExpired()) {
88 if (existingAccessToken.getRefreshToken() != null) {
89 refreshToken = existingAccessToken.getRefreshToken();
90
91
92
93 tokenStore.removeRefreshToken(refreshToken);
94 }
95 tokenStore.removeAccessToken(existingAccessToken);
96 }
97 else {
98
99 tokenStore.storeAccessToken(existingAccessToken, authentication);
100 return existingAccessToken;
101 }
102 }
103
104
105
106
107
108
109 if (refreshToken == null) {
110 refreshToken = createRefreshToken(authentication);
111 }
112
113
114 else if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
115 ExpiringOAuth2RefreshToken expiring = (ExpiringOAuth2RefreshToken) refreshToken;
116 if (System.currentTimeMillis() > expiring.getExpiration().getTime()) {
117 refreshToken = createRefreshToken(authentication);
118 }
119 }
120
121 OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
122 tokenStore.storeAccessToken(accessToken, authentication);
123
124 refreshToken = accessToken.getRefreshToken();
125 if (refreshToken != null) {
126 tokenStore.storeRefreshToken(refreshToken, authentication);
127 }
128 return accessToken;
129
130 }
131
132 @Transactional(noRollbackFor={InvalidTokenException.class, InvalidGrantException.class})
133 public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest)
134 throws AuthenticationException {
135
136 if (!supportRefreshToken) {
137 throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue);
138 }
139
140 OAuth2RefreshToken refreshToken = tokenStore.readRefreshToken(refreshTokenValue);
141 if (refreshToken == null) {
142 throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue);
143 }
144
145 OAuth2Authentication authentication = tokenStore.readAuthenticationForRefreshToken(refreshToken);
146 if (this.authenticationManager != null && !authentication.isClientOnly()) {
147
148
149 Authentication user = new PreAuthenticatedAuthenticationToken(authentication.getUserAuthentication(), "", authentication.getAuthorities());
150 user = authenticationManager.authenticate(user);
151 Object details = authentication.getDetails();
152 authentication = new OAuth2Authentication(authentication.getOAuth2Request(), user);
153 authentication.setDetails(details);
154 }
155 String clientId = authentication.getOAuth2Request().getClientId();
156 if (clientId == null || !clientId.equals(tokenRequest.getClientId())) {
157 throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue);
158 }
159
160
161
162 tokenStore.removeAccessTokenUsingRefreshToken(refreshToken);
163
164 if (isExpired(refreshToken)) {
165 tokenStore.removeRefreshToken(refreshToken);
166 throw new InvalidTokenException("Invalid refresh token (expired): " + refreshToken);
167 }
168
169 authentication = createRefreshedAuthentication(authentication, tokenRequest);
170
171 if (!reuseRefreshToken) {
172 tokenStore.removeRefreshToken(refreshToken);
173 refreshToken = createRefreshToken(authentication);
174 }
175
176 OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
177 tokenStore.storeAccessToken(accessToken, authentication);
178 if (!reuseRefreshToken) {
179 tokenStore.storeRefreshToken(accessToken.getRefreshToken(), authentication);
180 }
181 return accessToken;
182 }
183
184 public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
185 return tokenStore.getAccessToken(authentication);
186 }
187
188
189
190
191
192
193
194
195
196 private OAuth2Authenticationork/security/oauth2/provider/OAuth2Authentication.html#OAuth2Authentication">OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, TokenRequest request) {
197 OAuth2Authentication narrowed = authentication;
198 Set<String> scope = request.getScope();
199 OAuth2Request clientAuth = authentication.getOAuth2Request().refresh(request);
200 if (scope != null && !scope.isEmpty()) {
201 Set<String> originalScope = clientAuth.getScope();
202 if (originalScope == null || !originalScope.containsAll(scope)) {
203 throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope
204 + ".", originalScope);
205 }
206 else {
207 clientAuth = clientAuth.narrowScope(scope);
208 }
209 }
210 narrowed = new OAuth2Authentication(clientAuth, authentication.getUserAuthentication());
211 return narrowed;
212 }
213
214 protected boolean isExpired(OAuth2RefreshToken refreshToken) {
215 if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
216 ExpiringOAuth2RefreshToken expiringToken = (ExpiringOAuth2RefreshToken) refreshToken;
217 return expiringToken.getExpiration() == null
218 || System.currentTimeMillis() > expiringToken.getExpiration().getTime();
219 }
220 return false;
221 }
222
223 public OAuth2AccessToken readAccessToken(String accessToken) {
224 return tokenStore.readAccessToken(accessToken);
225 }
226
227 public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException,
228 InvalidTokenException {
229 OAuth2AccessToken accessToken = tokenStore.readAccessToken(accessTokenValue);
230 if (accessToken == null) {
231 throw new InvalidTokenException("Invalid access token: " + accessTokenValue);
232 }
233 else if (accessToken.isExpired()) {
234 tokenStore.removeAccessToken(accessToken);
235 throw new InvalidTokenException("Access token expired: " + accessTokenValue);
236 }
237
238 OAuth2Authentication result = tokenStore.readAuthentication(accessToken);
239 if (result == null) {
240
241 throw new InvalidTokenException("Invalid access token: " + accessTokenValue);
242 }
243 if (clientDetailsService != null) {
244 String clientId = result.getOAuth2Request().getClientId();
245 try {
246 clientDetailsService.loadClientByClientId(clientId);
247 }
248 catch (ClientRegistrationException e) {
249 throw new InvalidTokenException("Client not valid: " + clientId, e);
250 }
251 }
252 return result;
253 }
254
255 public String getClientId(String tokenValue) {
256 OAuth2Authentication authentication = tokenStore.readAuthentication(tokenValue);
257 if (authentication == null) {
258 throw new InvalidTokenException("Invalid access token: " + tokenValue);
259 }
260 OAuth2Request clientAuth = authentication.getOAuth2Request();
261 if (clientAuth == null) {
262 throw new InvalidTokenException("Invalid access token (no client id): " + tokenValue);
263 }
264 return clientAuth.getClientId();
265 }
266
267 public boolean revokeToken(String tokenValue) {
268 OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
269 if (accessToken == null) {
270 return false;
271 }
272 if (accessToken.getRefreshToken() != null) {
273 tokenStore.removeRefreshToken(accessToken.getRefreshToken());
274 }
275 tokenStore.removeAccessToken(accessToken);
276 return true;
277 }
278
279 private OAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) {
280 if (!isSupportRefreshToken(authentication.getOAuth2Request())) {
281 return null;
282 }
283 int validitySeconds = getRefreshTokenValiditySeconds(authentication.getOAuth2Request());
284 String value = UUID.randomUUID().toString();
285 if (validitySeconds > 0) {
286 return new DefaultExpiringOAuth2RefreshToken(value, new Date(System.currentTimeMillis()
287 + (validitySeconds * 1000L)));
288 }
289 return new DefaultOAuth2RefreshToken(value);
290 }
291
292 private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) {
293 DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString());
294 int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request());
295 if (validitySeconds > 0) {
296 token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L)));
297 }
298 token.setRefreshToken(refreshToken);
299 token.setScope(authentication.getOAuth2Request().getScope());
300
301 return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token;
302 }
303
304
305
306
307
308
309
310 protected int getAccessTokenValiditySeconds(OAuth2Request clientAuth) {
311 if (clientDetailsService != null) {
312 ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId());
313 Integer validity = client.getAccessTokenValiditySeconds();
314 if (validity != null) {
315 return validity;
316 }
317 }
318 return accessTokenValiditySeconds;
319 }
320
321
322
323
324
325
326
327 protected int getRefreshTokenValiditySeconds(OAuth2Request clientAuth) {
328 if (clientDetailsService != null) {
329 ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId());
330 Integer validity = client.getRefreshTokenValiditySeconds();
331 if (validity != null) {
332 return validity;
333 }
334 }
335 return refreshTokenValiditySeconds;
336 }
337
338
339
340
341
342
343
344
345 protected boolean isSupportRefreshToken(OAuth2Request clientAuth) {
346 if (clientDetailsService != null) {
347 ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId());
348 return client.getAuthorizedGrantTypes().contains("refresh_token");
349 }
350 return this.supportRefreshToken;
351 }
352
353
354
355
356
357
358 public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) {
359 this.accessTokenEnhancer = accessTokenEnhancer;
360 }
361
362
363
364
365
366
367
368 public void setRefreshTokenValiditySeconds(int refreshTokenValiditySeconds) {
369 this.refreshTokenValiditySeconds = refreshTokenValiditySeconds;
370 }
371
372
373
374
375
376
377
378
379 public void setAccessTokenValiditySeconds(int accessTokenValiditySeconds) {
380 this.accessTokenValiditySeconds = accessTokenValiditySeconds;
381 }
382
383
384
385
386
387
388 public void setSupportRefreshToken(boolean supportRefreshToken) {
389 this.supportRefreshToken = supportRefreshToken;
390 }
391
392
393
394
395
396
397 public void setReuseRefreshToken(boolean reuseRefreshToken) {
398 this.reuseRefreshToken = reuseRefreshToken;
399 }
400
401
402
403
404
405
406 public void setTokenStore(TokenStore tokenStore) {
407 this.tokenStore = tokenStore;
408 }
409
410
411
412
413
414
415
416 public void setAuthenticationManager(AuthenticationManager authenticationManager) {
417 this.authenticationManager = authenticationManager;
418 }
419
420
421
422
423
424
425
426 public void setClientDetailsService(ClientDetailsService clientDetailsService) {
427 this.clientDetailsService = clientDetailsService;
428 }
429
430 }