/oauth2/rest_token impl
parent
df8113d18a
commit
beac2d1f00
|
@ -53,7 +53,7 @@ public class WebSecurityConfigurer {
|
|||
http.authorizeHttpRequests(matcherRegistry -> {
|
||||
// permitAll() 的URL路径属于公开访问,不需要权限
|
||||
matcherRegistry
|
||||
.requestMatchers("/favicon.ico*", "/oauth/rest_token*", "*.js", "*.css").permitAll()
|
||||
.requestMatchers("/favicon.ico*", "/oauth2/rest_token*", "*.js", "*.css").permitAll()
|
||||
.requestMatchers("/api/public/**").permitAll()
|
||||
.requestMatchers(HttpMethod.GET, "/login*").anonymous()
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package com.monkeyk.sos.web.authentication;
|
||||
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
|
||||
/**
|
||||
* 2023/10/31 10:35
|
||||
*
|
||||
* @author Shengzhao Li
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public abstract class AbstractAuthenticationRestConverter implements AuthenticationRestConverter {
|
||||
|
||||
static final String ACCESS_TOKEN_REQUEST_ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2";
|
||||
|
||||
|
||||
protected void throwError(String errorCode, String parameterName, String errorUri) {
|
||||
OAuth2Error error = new OAuth2Error(errorCode, "OAuth 2.0 Parameter: " + parameterName, errorUri);
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.monkeyk.sos.web.authentication;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 2023/10/31 10:27
|
||||
*
|
||||
* @author Shengzhao Li
|
||||
* @see org.springframework.security.web.authentication.AuthenticationConverter
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public interface AuthenticationRestConverter {
|
||||
|
||||
/**
|
||||
* 从请求参数中转化到 Authentication
|
||||
*
|
||||
* @param parameters 请求参数
|
||||
* @return Authentication or null
|
||||
*/
|
||||
Authentication convert(Map<String, String> parameters);
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package com.monkeyk.sos.web.authentication;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 2023/10/31 10:30
|
||||
*
|
||||
* @author Shengzhao Li
|
||||
* @see org.springframework.security.oauth2.server.authorization.web.authentication.DelegatingAuthenticationConverter
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public final class DelegatingAuthenticationRestConverter implements AuthenticationRestConverter {
|
||||
|
||||
private final List<AuthenticationRestConverter> converters;
|
||||
|
||||
/**
|
||||
* Constructs a {@code DelegatingAuthenticationConverter} using the provided parameters.
|
||||
*
|
||||
* @param converters a {@code List} of {@link AuthenticationConverter}(s)
|
||||
*/
|
||||
public DelegatingAuthenticationRestConverter(List<AuthenticationRestConverter> converters) {
|
||||
Assert.notEmpty(converters, "converters cannot be empty");
|
||||
this.converters = Collections.unmodifiableList(new LinkedList<>(converters));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Authentication convert(Map<String, String> parameters) {
|
||||
Assert.notNull(parameters, "parameters cannot be null");
|
||||
for (AuthenticationRestConverter converter : this.converters) {
|
||||
Authentication authentication = converter.convert(parameters);
|
||||
if (authentication != null) {
|
||||
return authentication;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package com.monkeyk.sos.web.authentication;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeAuthenticationToken;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 2023/10/31 10:33
|
||||
*
|
||||
* @author Shengzhao Li
|
||||
* @see org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeAuthenticationConverter
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public final class OAuth2AuthorizationCodeAuthenticationRestConverter extends AbstractAuthenticationRestConverter {
|
||||
|
||||
|
||||
@Override
|
||||
public Authentication convert(Map<String, String> parameters) {
|
||||
// grant_type (REQUIRED)
|
||||
String grantType = parameters.get(OAuth2ParameterNames.GRANT_TYPE);
|
||||
if (!AuthorizationGrantType.AUTHORIZATION_CODE.getValue().equals(grantType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
// MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getParameters(request);
|
||||
|
||||
// code (REQUIRED)
|
||||
String code = parameters.get(OAuth2ParameterNames.CODE);
|
||||
if (!StringUtils.hasText(code)) {
|
||||
throwError(
|
||||
OAuth2ErrorCodes.INVALID_REQUEST,
|
||||
OAuth2ParameterNames.CODE,
|
||||
ACCESS_TOKEN_REQUEST_ERROR_URI);
|
||||
}
|
||||
|
||||
// redirect_uri (REQUIRED)
|
||||
// Required only if the "redirect_uri" parameter was included in the authorization request
|
||||
String redirectUri = parameters.get(OAuth2ParameterNames.REDIRECT_URI);
|
||||
if (!StringUtils.hasText(redirectUri)) {
|
||||
throwError(
|
||||
OAuth2ErrorCodes.INVALID_REQUEST,
|
||||
OAuth2ParameterNames.REDIRECT_URI,
|
||||
ACCESS_TOKEN_REQUEST_ERROR_URI);
|
||||
}
|
||||
|
||||
Map<String, Object> additionalParameters = new HashMap<>();
|
||||
parameters.forEach((key, value) -> {
|
||||
if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) &&
|
||||
!key.equals(OAuth2ParameterNames.CLIENT_ID) &&
|
||||
!key.equals(OAuth2ParameterNames.CODE) &&
|
||||
!key.equals(OAuth2ParameterNames.REDIRECT_URI)) {
|
||||
// additionalParameters.put(key, (value.size() == 1) ? value.get(0) : value.toArray(new String[0]));
|
||||
additionalParameters.put(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return new OAuth2AuthorizationCodeAuthenticationToken(
|
||||
code, clientPrincipal, redirectUri, additionalParameters);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package com.monkeyk.sos.web.authentication;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationToken;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 2023/10/31 10:33
|
||||
*
|
||||
* @author Shengzhao Li
|
||||
* @see org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2ClientCredentialsAuthenticationConverter
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public final class OAuth2ClientCredentialsAuthenticationRestConverter extends AbstractAuthenticationRestConverter {
|
||||
|
||||
|
||||
@Override
|
||||
public Authentication convert(Map<String, String> parameters) {
|
||||
// grant_type (REQUIRED)
|
||||
String grantType = parameters.get(OAuth2ParameterNames.GRANT_TYPE);
|
||||
if (!AuthorizationGrantType.CLIENT_CREDENTIALS.getValue().equals(grantType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
// MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getParameters(request);
|
||||
|
||||
// scope (OPTIONAL)
|
||||
String scope = parameters.get(OAuth2ParameterNames.SCOPE);
|
||||
// if (StringUtils.hasText(scope) &&
|
||||
// parameters.get(OAuth2ParameterNames.SCOPE).size() != 1) {
|
||||
// throwError(
|
||||
// OAuth2ErrorCodes.INVALID_REQUEST,
|
||||
// OAuth2ParameterNames.SCOPE,
|
||||
// ACCESS_TOKEN_REQUEST_ERROR_URI);
|
||||
// }
|
||||
Set<String> requestedScopes = null;
|
||||
if (StringUtils.hasText(scope)) {
|
||||
requestedScopes = new HashSet<>(
|
||||
Arrays.asList(StringUtils.delimitedListToStringArray(scope, " ")));
|
||||
}
|
||||
|
||||
Map<String, Object> additionalParameters = new HashMap<>();
|
||||
parameters.forEach((key, value) -> {
|
||||
if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) &&
|
||||
!key.equals(OAuth2ParameterNames.SCOPE)) {
|
||||
additionalParameters.put(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return new OAuth2ClientCredentialsAuthenticationToken(
|
||||
clientPrincipal, requestedScopes, additionalParameters);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.monkeyk.sos.web.authentication;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2DeviceCodeAuthenticationToken;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 2023/10/31 10:33
|
||||
*
|
||||
* @author Shengzhao Li
|
||||
* @see org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2DeviceCodeAuthenticationConverter
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public final class OAuth2DeviceCodeAuthenticationRestConverter extends AbstractAuthenticationRestConverter {
|
||||
|
||||
|
||||
@Override
|
||||
public Authentication convert(Map<String, String> parameters) {
|
||||
// grant_type (REQUIRED)
|
||||
String grantType = parameters.get(OAuth2ParameterNames.GRANT_TYPE);
|
||||
if (!AuthorizationGrantType.DEVICE_CODE.getValue().equals(grantType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
// MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getParameters(request);
|
||||
|
||||
// device_code (REQUIRED)
|
||||
String deviceCode = parameters.get(OAuth2ParameterNames.DEVICE_CODE);
|
||||
if (!StringUtils.hasText(deviceCode)) {
|
||||
throwError(
|
||||
OAuth2ErrorCodes.INVALID_REQUEST,
|
||||
OAuth2ParameterNames.DEVICE_CODE,
|
||||
ACCESS_TOKEN_REQUEST_ERROR_URI);
|
||||
}
|
||||
|
||||
Map<String, Object> additionalParameters = new HashMap<>();
|
||||
parameters.forEach((key, value) -> {
|
||||
if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) &&
|
||||
!key.equals(OAuth2ParameterNames.CLIENT_ID) &&
|
||||
!key.equals(OAuth2ParameterNames.DEVICE_CODE)) {
|
||||
additionalParameters.put(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return new OAuth2DeviceCodeAuthenticationToken(deviceCode, clientPrincipal, additionalParameters);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.monkeyk.sos.web.authentication;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2RefreshTokenAuthenticationToken;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 2023/10/31 10:33
|
||||
*
|
||||
* @author Shengzhao Li
|
||||
* @see org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2RefreshTokenAuthenticationConverter
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public final class OAuth2RefreshTokenAuthenticationRestConverter extends AbstractAuthenticationRestConverter {
|
||||
|
||||
|
||||
@Override
|
||||
public Authentication convert(Map<String, String> parameters) {
|
||||
// grant_type (REQUIRED)
|
||||
String grantType = parameters.get(OAuth2ParameterNames.GRANT_TYPE);
|
||||
if (!AuthorizationGrantType.REFRESH_TOKEN.getValue().equals(grantType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
// MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getParameters(request);
|
||||
|
||||
// refresh_token (REQUIRED)
|
||||
String refreshToken = parameters.get(OAuth2ParameterNames.REFRESH_TOKEN);
|
||||
if (!StringUtils.hasText(refreshToken)) {
|
||||
throwError(
|
||||
OAuth2ErrorCodes.INVALID_REQUEST,
|
||||
OAuth2ParameterNames.REFRESH_TOKEN,
|
||||
ACCESS_TOKEN_REQUEST_ERROR_URI);
|
||||
}
|
||||
|
||||
// scope (OPTIONAL)
|
||||
String scope = parameters.get(OAuth2ParameterNames.SCOPE);
|
||||
// if (!StringUtils.hasText(scope)) {
|
||||
// throwError(
|
||||
// OAuth2ErrorCodes.INVALID_REQUEST,
|
||||
// OAuth2ParameterNames.SCOPE,
|
||||
// ACCESS_TOKEN_REQUEST_ERROR_URI);
|
||||
// }
|
||||
Set<String> requestedScopes = null;
|
||||
if (StringUtils.hasText(scope)) {
|
||||
requestedScopes = new HashSet<>(
|
||||
Arrays.asList(StringUtils.delimitedListToStringArray(scope, " ")));
|
||||
}
|
||||
|
||||
Map<String, Object> additionalParameters = new HashMap<>();
|
||||
parameters.forEach((key, value) -> {
|
||||
if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) &&
|
||||
!key.equals(OAuth2ParameterNames.REFRESH_TOKEN) &&
|
||||
!key.equals(OAuth2ParameterNames.SCOPE)) {
|
||||
additionalParameters.put(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return new OAuth2RefreshTokenAuthenticationToken(
|
||||
refreshToken, clientPrincipal, requestedScopes, additionalParameters);
|
||||
}
|
||||
}
|
|
@ -11,23 +11,38 @@
|
|||
*/
|
||||
package com.monkeyk.sos.web.controller;
|
||||
|
||||
import com.monkeyk.sos.web.WebUtils;
|
||||
import com.monkeyk.sos.web.authentication.*;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.core.*;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
|
||||
import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMessageConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AccessTokenAuthenticationToken;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -45,165 +60,115 @@ public class OAuthRestController implements InitializingBean, ApplicationContext
|
|||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(OAuthRestController.class);
|
||||
|
||||
// @Autowired
|
||||
// private ClientDetailsService clientDetailsService;
|
||||
//
|
||||
// // consumerTokenServices,defaultAuthorizationServerTokenServices
|
||||
// @Autowired
|
||||
// @Qualifier("defaultAuthorizationServerTokenServices")
|
||||
// private AuthorizationServerTokenServices tokenServices;
|
||||
// @Autowired
|
||||
// private AuthorizationCodeServices authorizationCodeServices;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
// private AuthenticationManager authenticationManager;
|
||||
|
||||
// private OAuth2RequestFactory oAuth2RequestFactory;
|
||||
//
|
||||
// private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator();
|
||||
// private WebResponseExceptionTranslator providerExceptionHandler = new DefaultWebResponseExceptionTranslator();
|
||||
private static final String DEFAULT_ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2";
|
||||
|
||||
|
||||
@RequestMapping(value = "/oauth2/rest_token", method = RequestMethod.POST)
|
||||
private final AuthenticationRestConverter authenticationConverter;
|
||||
|
||||
private final HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter =
|
||||
new OAuth2AccessTokenResponseHttpMessageConverter();
|
||||
private final HttpMessageConverter<OAuth2Error> errorHttpResponseConverter =
|
||||
new OAuth2ErrorHttpMessageConverter();
|
||||
|
||||
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
public OAuthRestController() {
|
||||
|
||||
this.authenticationConverter = new DelegatingAuthenticationRestConverter(
|
||||
Arrays.asList(
|
||||
new OAuth2AuthorizationCodeAuthenticationRestConverter(),
|
||||
new OAuth2RefreshTokenAuthenticationRestConverter(),
|
||||
new OAuth2ClientCredentialsAuthenticationRestConverter(),
|
||||
new OAuth2DeviceCodeAuthenticationRestConverter()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace OAuth2TokenEndpointFilter flow use restful API
|
||||
*
|
||||
* @param parameters request params
|
||||
*/
|
||||
@PostMapping("/oauth2/rest_token")
|
||||
@ResponseBody
|
||||
public OAuth2AccessToken postAccessToken(@RequestBody Map<String, String> parameters) {
|
||||
public void postAccessToken(@RequestBody Map<String, String> parameters, HttpServletResponse response) throws IOException {
|
||||
|
||||
try {
|
||||
String grantType = parameters.get(OAuth2ParameterNames.GRANT_TYPE);
|
||||
if (grantType == null) {
|
||||
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.GRANT_TYPE);
|
||||
}
|
||||
|
||||
// String clientId = getClientId(parameters);
|
||||
// ClientDetails authenticatedClient = clientDetailsService.loadClientByClientId(clientId);
|
||||
//
|
||||
// //validate client_secret
|
||||
// String clientSecret = getClientSecret(parameters);
|
||||
// if (clientSecret == null || clientSecret.equals("")) {
|
||||
// throw new InvalidClientException("Bad client credentials");
|
||||
// } else {
|
||||
// if (!this.passwordEncoder.matches(clientSecret, authenticatedClient.getClientSecret())) {
|
||||
// throw new InvalidClientException("Bad client credentials");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// TokenRequest tokenRequest = oAuth2RequestFactory.createTokenRequest(parameters, authenticatedClient);
|
||||
Authentication authorizationGrantAuthentication = this.authenticationConverter.convert(parameters);
|
||||
if (authorizationGrantAuthentication == null) {
|
||||
throwError(OAuth2ErrorCodes.UNSUPPORTED_GRANT_TYPE, OAuth2ParameterNames.GRANT_TYPE);
|
||||
}
|
||||
if (authorizationGrantAuthentication instanceof AbstractAuthenticationToken) {
|
||||
((AbstractAuthenticationToken) authorizationGrantAuthentication)
|
||||
// .setDetails(this.authenticationDetailsSource.buildDetails(request));
|
||||
.setDetails(new WebAuthenticationDetails(WebUtils.getIp(), null));
|
||||
}
|
||||
|
||||
// if (clientId != null && !clientId.equals("")) {
|
||||
// // Only validate the client details if a client authenticated during this
|
||||
// // request.
|
||||
// if (!clientId.equals(tokenRequest.getClientId())) {
|
||||
// // double check to make sure that the client ID in the token request is the same as that in the
|
||||
// // authenticated client
|
||||
// throw new InvalidClientException("Given client ID does not match authenticated client");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);
|
||||
|
||||
// final String grantType = tokenRequest.getGrantType();
|
||||
// if (!StringUtils.hasText(grantType)) {
|
||||
// throw new InvalidRequestException("Missing grant type");
|
||||
// }
|
||||
// if (grantType.equals("implicit")) {
|
||||
// throw new InvalidGrantException("Implicit grant type not supported from token endpoint");
|
||||
// }
|
||||
//
|
||||
// if (isAuthCodeRequest(parameters)) {
|
||||
// // The scope was requested or determined during the authorization step
|
||||
// if (!tokenRequest.getScope().isEmpty()) {
|
||||
// LOG.debug("Clearing scope of incoming token request");
|
||||
// tokenRequest.setScope(Collections.<String>emptySet());
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// if (isRefreshTokenRequest(parameters)) {
|
||||
// // A refresh token has its own default scopes, so we should ignore any added by the factory here.
|
||||
// tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)));
|
||||
// }
|
||||
//
|
||||
// OAuth2AccessToken token = getTokenGranter(grantType).grant(grantType, tokenRequest);
|
||||
// if (token == null) {
|
||||
// throw new UnsupportedGrantTypeException("Unsupported grant type: " + grantType);
|
||||
// }
|
||||
|
||||
|
||||
// return token;
|
||||
throw new UnsupportedOperationException("Not yet implements");
|
||||
}
|
||||
|
||||
// protected TokenGranter getTokenGranter(String grantType) {
|
||||
//
|
||||
// if ("authorization_code".equals(grantType)) {
|
||||
// return new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetailsService, this.oAuth2RequestFactory);
|
||||
// } else if ("password".equals(grantType)) {
|
||||
// return new ResourceOwnerPasswordTokenGranter(getAuthenticationManager(), tokenServices, clientDetailsService, this.oAuth2RequestFactory);
|
||||
// } else if ("refresh_token".equals(grantType)) {
|
||||
// return new RefreshTokenGranter(tokenServices, clientDetailsService, this.oAuth2RequestFactory);
|
||||
// } else if ("client_credentials".equals(grantType)) {
|
||||
// return new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, this.oAuth2RequestFactory);
|
||||
// } else if ("implicit".equals(grantType)) {
|
||||
// return new ImplicitTokenGranter(tokenServices, clientDetailsService, this.oAuth2RequestFactory);
|
||||
// } else {
|
||||
// throw new UnsupportedGrantTypeException("Unsupport grant_type: " + grantType);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// @ExceptionHandler(Exception.class)
|
||||
// public ResponseEntity<OAuth2Exception> handleException(Exception e) throws Exception {
|
||||
// LOG.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
|
||||
// return getExceptionTranslator().translate(e);
|
||||
// }
|
||||
|
||||
// @ExceptionHandler(ClientRegistrationException.class)
|
||||
// public ResponseEntity<OAuth2Exception> handleClientRegistrationException(Exception e) throws Exception {
|
||||
// LOG.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
|
||||
// return getExceptionTranslator().translate(new BadClientCredentialsException());
|
||||
// }
|
||||
//
|
||||
// @ExceptionHandler(OAuth2Exception.class)
|
||||
// public ResponseEntity<OAuth2Exception> handleException(OAuth2Exception e) throws Exception {
|
||||
// LOG.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
|
||||
// return getExceptionTranslator().translate(e);
|
||||
// }
|
||||
|
||||
|
||||
// private boolean isRefreshTokenRequest(Map<String, String> parameters) {
|
||||
// return "refresh_token".equals(parameters.get(OAuth2Utils.GRANT_TYPE)) && parameters.get("refresh_token") != null;
|
||||
// }
|
||||
//
|
||||
// private boolean isAuthCodeRequest(Map<String, String> parameters) {
|
||||
// return "authorization_code".equals(parameters.get(OAuth2Utils.GRANT_TYPE)) && parameters.get("code") != null;
|
||||
// }
|
||||
|
||||
|
||||
// protected String getClientId(Map<String, String> parameters) {
|
||||
// return parameters.get(OAuth2Utils.CLIENT_ID);
|
||||
// }
|
||||
|
||||
protected String getClientSecret(Map<String, String> parameters) {
|
||||
return parameters.get("client_secret");
|
||||
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
|
||||
(OAuth2AccessTokenAuthenticationToken) this.authenticationManager.authenticate(authorizationGrantAuthentication);
|
||||
this.sendAccessTokenResponse(response, accessTokenAuthentication);
|
||||
} catch (OAuth2AuthenticationException ex) {
|
||||
SecurityContextHolder.clearContext();
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Token request failed: {}", ex.getError(), ex);
|
||||
}
|
||||
this.sendErrorResponse(response, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// private AuthenticationManager getAuthenticationManager() {
|
||||
// return this.authenticationManager;
|
||||
// }
|
||||
private void sendErrorResponse(HttpServletResponse response,
|
||||
AuthenticationException exception) throws IOException {
|
||||
|
||||
OAuth2Error error = ((OAuth2AuthenticationException) exception).getError();
|
||||
ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
|
||||
httpResponse.setStatusCode(HttpStatus.BAD_REQUEST);
|
||||
this.errorHttpResponseConverter.write(error, null, httpResponse);
|
||||
}
|
||||
|
||||
private void sendAccessTokenResponse(HttpServletResponse response, Authentication authentication) throws IOException {
|
||||
|
||||
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
|
||||
(OAuth2AccessTokenAuthenticationToken) authentication;
|
||||
|
||||
OAuth2AccessToken accessToken = accessTokenAuthentication.getAccessToken();
|
||||
OAuth2RefreshToken refreshToken = accessTokenAuthentication.getRefreshToken();
|
||||
Map<String, Object> additionalParameters = accessTokenAuthentication.getAdditionalParameters();
|
||||
|
||||
OAuth2AccessTokenResponse.Builder builder =
|
||||
OAuth2AccessTokenResponse.withToken(accessToken.getTokenValue())
|
||||
.tokenType(accessToken.getTokenType())
|
||||
.scopes(accessToken.getScopes());
|
||||
if (accessToken.getIssuedAt() != null && accessToken.getExpiresAt() != null) {
|
||||
builder.expiresIn(ChronoUnit.SECONDS.between(accessToken.getIssuedAt(), accessToken.getExpiresAt()));
|
||||
}
|
||||
if (refreshToken != null) {
|
||||
builder.refreshToken(refreshToken.getTokenValue());
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(additionalParameters)) {
|
||||
builder.additionalParameters(additionalParameters);
|
||||
}
|
||||
OAuth2AccessTokenResponse accessTokenResponse = builder.build();
|
||||
ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
|
||||
this.accessTokenHttpResponseConverter.write(accessTokenResponse, null, httpResponse);
|
||||
}
|
||||
|
||||
|
||||
private static void throwError(String errorCode, String parameterName) {
|
||||
OAuth2Error error = new OAuth2Error(errorCode, "OAuth 2.0 Parameter: " + parameterName, DEFAULT_ERROR_URI);
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
// Assert.state(clientDetailsService != null, "ClientDetailsService must be provided");
|
||||
// Assert.state(authenticationManager != null, "AuthenticationManager must be provided");
|
||||
|
||||
Assert.notNull(this.passwordEncoder, "PasswordEncoder is null");
|
||||
|
||||
// oAuth2RequestFactory = new DefaultOAuth2RequestFactory(clientDetailsService);
|
||||
}
|
||||
|
||||
// protected WebResponseExceptionTranslator getExceptionTranslator() {
|
||||
// return providerExceptionHandler;
|
||||
// }
|
||||
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
|
@ -211,4 +176,5 @@ public class OAuthRestController implements InitializingBean, ApplicationContext
|
|||
// this.authenticationManager = (AuthenticationManager) applicationContext.getBean("authenticationManagerBean");
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue