4
5
6
8
10
11
12
13
14
15
16
package
org.springframework.security.oauth2.client.token;
18
import
java.util.Collections;
19
import
java.util.List;
21
import
org.springframework.security.access.AccessDeniedException;
22
import
org.springframework.security.authentication.AnonymousAuthenticationToken;
23
import
org.springframework.security.authentication.InsufficientAuthenticationException;
24
import
org.springframework.security.core.Authentication;
25
import
org.springframework.security.core.context.SecurityContextHolder;
26
import
org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
27
import
org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
28
import
org.springframework.security.oauth2.client.resource.UserRedirectRequiredException;
29
import
org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
30
import
org.springframework.security.oauth2.common.OAuth2AccessToken;
31
import
org.springframework.security.oauth2.common.OAuth2RefreshToken;
32
import
org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
34
35
36
37
38
39
40
41
42
public
class
AccessTokenProviderChain
extends
OAuth2AccessTokenSupport
43
implements
AccessTokenProvider
{
45
private
final
List<AccessTokenProvider> chain;
47
private
ClientTokenServices
clientTokenServices;
49
public
AccessTokenProviderChain
(List<?
extends
AccessTokenProvider> chain) {
50
this
.chain = chain ==
null
? Collections.<AccessTokenProvider> emptyList()
51
: Collections.unmodifiableList(chain);
54
55
56
57
58
59
public
void
setClientTokenServices(
ClientTokenServices
clientTokenServices) {
60
this
.clientTokenServices = clientTokenServices;
63
public
boolean
supportsResource(
OAuth2ProtectedResourceDetails
resource) {
64
for
(
AccessTokenProvider
tokenProvider : chain) {
65
if
(tokenProvider.supportsResource(resource)) {
66
return
true
;
69
return
false;
72
public
boolean
supportsRefresh(
OAuth2ProtectedResourceDetails
resource) {
73
for
(
AccessTokenProvider
tokenProvider : chain) {
74
if
(tokenProvider.supportsRefresh(resource)) {
75
return
true
;
78
return
false;
81
public
OAuth2AccessToken
obtainAccessToken(
OAuth2ProtectedResourceDetails
resource,
82
AccessTokenRequest request)
83
throws
UserRedirectRequiredException, AccessDeniedException {
85
OAuth2AccessToken accessToken =
null
;
86
OAuth2AccessToken existingToken =
null
;
87
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
89
if
(auth instanceof AnonymousAuthenticationToken) {
90
if
(!resource.isClientOnly()) {
91
throw
new
InsufficientAuthenticationException(
92
"Authentication is required to obtain an access token (anonymous not allowed)"
);
96
if
(resource.isClientOnly() || (auth !=
null
&& auth.isAuthenticated())) {
97
existingToken = request.getExistingToken();
98
if
(existingToken ==
null
&& clientTokenServices !=
null
) {
99
existingToken = clientTokenServices.getAccessToken(resource, auth);
100
}
102
if
(existingToken !=
null
) {
103
if
(existingToken.isExpired()) {
104
if
(clientTokenServices !=
null
) {
105
clientTokenServices.removeAccessToken(resource, auth);
106
}
107
OAuth2RefreshToken refreshToken = existingToken.getRefreshToken();
108
if
(refreshToken !=
null
&& !resource.isClientOnly()) {
109
accessToken = refreshAccessToken(resource, refreshToken, request);
110
}
111
}
112
else
{
113
accessToken = existingToken;
114
}
115
}
116
}
117
119
if
(accessToken ==
null
) {
120
121
accessToken = obtainNewAccessTokenInternal(resource, request);
123
if
(accessToken ==
null
) {
124
throw
new
IllegalStateException(
125
"An OAuth 2 access token must be obtained or an exception thrown."
);
126
}
127
}
129
if
(clientTokenServices !=
null
130
&& (resource.isClientOnly() || auth !=
null
&& auth.isAuthenticated())) {
131
clientTokenServices.saveAccessToken(resource, auth, accessToken);
132
}
134
return
accessToken;
135
}
137
protected
OAuth2AccessToken
obtainNewAccessTokenInternal(
138
OAuth2ProtectedResourceDetails details,
AccessTokenRequest
request)
139
throws
UserRedirectRequiredException, AccessDeniedException {
141
if
(request.isError()) {
142
143
throw
OAuth2Exception.valueOf(request.toSingleValueMap());
144
}
146
for
(
AccessTokenProvider
tokenProvider : chain) {
147
if
(tokenProvider.supportsResource(details)) {
148
return
tokenProvider.obtainAccessToken(details, request);
149
}
150
}
152
throw
new
OAuth2AccessDeniedException
(
153
"Unable to obtain a new access token for resource '"
+ details.getId()
154
+
"'. The provider manager is not configured to support it."
,
155
details);
156
}
158
159
160
161
162
163
164
165
166
public
OAuth2AccessToken
refreshAccessToken(
OAuth2ProtectedResourceDetails
resource,
167
OAuth2RefreshToken refreshToken,
AccessTokenRequest
request)
168
throws
UserRedirectRequiredException
{
169
for
(
AccessTokenProvider
tokenProvider : chain) {
170
if
(tokenProvider.supportsRefresh(resource)) {
171
DefaultOAuth2AccessToken refreshedAccessToken =
new
DefaultOAuth2AccessToken
(
172
tokenProvider.refreshAccessToken(resource, refreshToken,
173
request));
174
if
(refreshedAccessToken.getRefreshToken() ==
null
) {
175
176
refreshedAccessToken.setRefreshToken(refreshToken);
177
}
178
return
refreshedAccessToken;
179
}
180
}
181
throw
new
OAuth2AccessDeniedException
(
182
"Unable to obtain a new access token for resource '"
+ resource.getId()
183
+
"'. The provider manager is not configured to support it."
,
184
resource);
185
}