protected OAuth2AccessToken acquireAccessToken(OAuth2ClientContext oauth2Context)
throws UserRedirectRequiredException {
AccessTokenRequest accessTokenRequest = oauth2Context.getAccessTokenRequest();
if (accessTokenRequest == null) {
throw new AccessTokenRequiredException(
"No OAuth 2 security context has been established. Unable to access resource '"
+ this.resource.getId() + "'.", resource);
// Transfer the preserved state from the (longer lived) context to the current request.
String stateKey = accessTokenRequest.getStateKey();
// 如果请求中没有状态码,则从上下文中获取预设的状态码(如果存在长生命周期的上下文,例如已获得授权的会话)
if (stateKey != null) {
accessTokenRequest.setPreservedState(oauth2Context.removePreservedState(stateKey));
OAuth2AccessToken existingToken = oauth2Context.getAccessToken();
if (existingToken != null) {
accessTokenRequest.setExistingToken(existingToken);
OAuth2AccessToken accessToken = null;
accessToken = accessTokenProvider.obtainAccessToken(resource, accessTokenRequest);
if (accessToken == null || accessToken.getValue() == null) {
throw new IllegalStateException(
"Access token provider returned a null access token, which is illegal according to the contract.");
oauth2Context.setAccessToken(accessToken);
return accessToken;
}
@Override
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
Map<String, String> parameters = tokenRequest.getRequestParameters();
String authorizationCode = parameters.get("code");
String redirectUri = parameters.get(OAuth2Utils.REDIRECT_URI);
if (authorizationCode == null) {
throw new InvalidRequestException("An authorization code must be supplied.");
// 从授权码服务中根据授权码获取认证信息
OAuth2Authentication storedAuth = authorizationCodeServices.consumeAuthorizationCode(authorizationCode);
if (storedAuth == null) {
throw new InvalidGrantException("Invalid authorization code: " + authorizationCode);
OAuth2Request pendingOAuth2Request = storedAuth.getOAuth2Request();
// https://jira.springsource.org/browse/SECOAUTH-333
// This might be null, if the authorization was done without the redirect_uri parameter
String redirectUriApprovalParameter = pendingOAuth2Request.getRequestParameters().get(
OAuth2Utils.REDIRECT_URI);
if ((redirectUri != null || redirectUriApprovalParameter != null)
&& !pendingOAuth2Request.getRedirectUri().equals(redirectUri)) {
throw new RedirectMismatchException("Redirect URI mismatch.");
String pendingClientId = pendingOAuth2Request.getClientId();
String clientId = tokenRequest.getClientId();
if (clientId != null && !clientId.equals(pendingClientId)) {
// just a sanity check.
throw new InvalidClientException("Client ID mismatch");
// Secret is not required in the authorization request, so it won't be available
// in the pendingAuthorizationRequest. We do want to check that a secret is provided
// in the token request, but that happens elsewhere.
Map<String, String> combinedParameters = new HashMap<String, String>(pendingOAuth2Request
.getRequestParameters());
// Combine the parameters adding the new ones last so they override if there are any clashes
combinedParameters.putAll(parameters);
// Make a new stored request with the combined parameters
OAuth2Request finalStoredOAuth2Request = pendingOAuth2Request.createOAuth2Request(combinedParameters);
Authentication userAuth = storedAuth.getUserAuthentication();
return new OAuth2Authentication(finalStoredOAuth2Request, userAuth);
}