Merge branch 0.4.x into main
The following commits are merged using the default merge strategy.7e03795c58Remove issuer setting from samples2c4bd29f98Add logging for authentication providers74fe63a65bAdd logging for authentication filters
This commit is contained in:
@@ -17,6 +17,9 @@ package org.springframework.security.oauth2.server.authorization.authentication;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@@ -47,6 +50,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public final class ClientSecretAuthenticationProvider implements AuthenticationProvider {
|
||||
private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-3.2.1";
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final RegisteredClientRepository registeredClientRepository;
|
||||
private final CodeVerifierAuthenticator codeVerifierAuthenticator;
|
||||
private PasswordEncoder passwordEncoder;
|
||||
@@ -95,6 +99,10 @@ public final class ClientSecretAuthenticationProvider implements AuthenticationP
|
||||
throwInvalidClient(OAuth2ParameterNames.CLIENT_ID);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved registered client");
|
||||
}
|
||||
|
||||
if (!registeredClient.getClientAuthenticationMethods().contains(
|
||||
clientAuthentication.getClientAuthenticationMethod())) {
|
||||
throwInvalidClient("authentication_method");
|
||||
@@ -114,9 +122,17 @@ public final class ClientSecretAuthenticationProvider implements AuthenticationP
|
||||
throwInvalidClient("client_secret_expires_at");
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Validated client authentication parameters");
|
||||
}
|
||||
|
||||
// Validate the "code_verifier" parameter for the confidential client, if available
|
||||
this.codeVerifierAuthenticator.authenticateIfAvailable(clientAuthentication, registeredClient);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Authenticated client secret");
|
||||
}
|
||||
|
||||
return new OAuth2ClientAuthenticationToken(registeredClient,
|
||||
clientAuthentication.getClientAuthenticationMethod(), clientAuthentication.getCredentials());
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Base64;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
@@ -47,6 +50,7 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
final class CodeVerifierAuthenticator {
|
||||
private static final OAuth2TokenType AUTHORIZATION_CODE_TOKEN_TYPE = new OAuth2TokenType(OAuth2ParameterNames.CODE);
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final OAuth2AuthorizationService authorizationService;
|
||||
|
||||
CodeVerifierAuthenticator(OAuth2AuthorizationService authorizationService) {
|
||||
@@ -81,6 +85,10 @@ final class CodeVerifierAuthenticator {
|
||||
throwInvalidGrant(OAuth2ParameterNames.CODE);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved authorization with authorization code");
|
||||
}
|
||||
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
|
||||
@@ -90,10 +98,17 @@ final class CodeVerifierAuthenticator {
|
||||
if (registeredClient.getClientSettings().isRequireProofKey()) {
|
||||
throwInvalidGrant(PkceParameterNames.CODE_CHALLENGE);
|
||||
} else {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Did not authenticate code verifier since requireProofKey=false");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Validated code verifier parameters");
|
||||
}
|
||||
|
||||
String codeChallengeMethod = (String) authorizationRequest.getAdditionalParameters()
|
||||
.get(PkceParameterNames.CODE_CHALLENGE_METHOD);
|
||||
String codeVerifier = (String) parameters.get(PkceParameterNames.CODE_VERIFIER);
|
||||
@@ -101,6 +116,10 @@ final class CodeVerifierAuthenticator {
|
||||
throwInvalidGrant(PkceParameterNames.CODE_VERIFIER);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Authenticated code verifier");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.security.oauth2.server.authorization.authentication;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@@ -50,6 +53,7 @@ public final class JwtClientAssertionAuthenticationProvider implements Authentic
|
||||
private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-3.2.1";
|
||||
private static final ClientAuthenticationMethod JWT_CLIENT_ASSERTION_AUTHENTICATION_METHOD =
|
||||
new ClientAuthenticationMethod("urn:ietf:params:oauth:client-assertion-type:jwt-bearer");
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final RegisteredClientRepository registeredClientRepository;
|
||||
private final CodeVerifierAuthenticator codeVerifierAuthenticator;
|
||||
private JwtDecoderFactory<RegisteredClient> jwtDecoderFactory;
|
||||
@@ -84,6 +88,10 @@ public final class JwtClientAssertionAuthenticationProvider implements Authentic
|
||||
throwInvalidClient(OAuth2ParameterNames.CLIENT_ID);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved registered client");
|
||||
}
|
||||
|
||||
if (!registeredClient.getClientAuthenticationMethods().contains(ClientAuthenticationMethod.PRIVATE_KEY_JWT) &&
|
||||
!registeredClient.getClientAuthenticationMethods().contains(ClientAuthenticationMethod.CLIENT_SECRET_JWT)) {
|
||||
throwInvalidClient("authentication_method");
|
||||
@@ -101,6 +109,10 @@ public final class JwtClientAssertionAuthenticationProvider implements Authentic
|
||||
throwInvalidClient(OAuth2ParameterNames.CLIENT_ASSERTION, ex);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Validated client authentication parameters");
|
||||
}
|
||||
|
||||
// Validate the "code_verifier" parameter for the confidential client, if available
|
||||
this.codeVerifierAuthenticator.authenticateIfAvailable(clientAuthentication, registeredClient);
|
||||
|
||||
@@ -109,6 +121,10 @@ public final class JwtClientAssertionAuthenticationProvider implements Authentic
|
||||
ClientAuthenticationMethod.PRIVATE_KEY_JWT :
|
||||
ClientAuthenticationMethod.CLIENT_SECRET_JWT;
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Authenticated client assertion");
|
||||
}
|
||||
|
||||
return new OAuth2ClientAuthenticationToken(registeredClient, clientAuthenticationMethod, jwtAssertion);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,10 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@@ -72,6 +76,7 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
|
||||
new OAuth2TokenType(OAuth2ParameterNames.CODE);
|
||||
private static final OAuth2TokenType ID_TOKEN_TOKEN_TYPE =
|
||||
new OAuth2TokenType(OidcParameterNames.ID_TOKEN);
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final OAuth2AuthorizationService authorizationService;
|
||||
private final OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator;
|
||||
|
||||
@@ -99,11 +104,20 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
|
||||
getAuthenticatedClientElseThrowInvalidClient(authorizationCodeAuthentication);
|
||||
RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved registered client");
|
||||
}
|
||||
|
||||
OAuth2Authorization authorization = this.authorizationService.findByToken(
|
||||
authorizationCodeAuthentication.getCode(), AUTHORIZATION_CODE_TOKEN_TYPE);
|
||||
if (authorization == null) {
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved authorization with authorization code");
|
||||
}
|
||||
|
||||
OAuth2Authorization.Token<OAuth2AuthorizationCode> authorizationCode =
|
||||
authorization.getToken(OAuth2AuthorizationCode.class);
|
||||
|
||||
@@ -115,6 +129,9 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
|
||||
// Invalidate the authorization code given that a different client is attempting to use it
|
||||
authorization = OAuth2AuthenticationProviderUtils.invalidate(authorization, authorizationCode.getToken());
|
||||
this.authorizationService.save(authorization);
|
||||
if (this.logger.isWarnEnabled()) {
|
||||
this.logger.warn(LogMessage.format("Invalidated authorization code used by registered client '%s'", registeredClient.getId()));
|
||||
}
|
||||
}
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT);
|
||||
}
|
||||
@@ -128,6 +145,10 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Validated token request parameters");
|
||||
}
|
||||
|
||||
// @formatter:off
|
||||
DefaultOAuth2TokenContext.Builder tokenContextBuilder = DefaultOAuth2TokenContext.builder()
|
||||
.registeredClient(registeredClient)
|
||||
@@ -149,6 +170,11 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
|
||||
"The token generator failed to generate the access token.", ERROR_URI);
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Generated access token");
|
||||
}
|
||||
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(),
|
||||
generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());
|
||||
@@ -172,6 +198,11 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
|
||||
"The token generator failed to generate the refresh token.", ERROR_URI);
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Generated refresh token");
|
||||
}
|
||||
|
||||
refreshToken = (OAuth2RefreshToken) generatedRefreshToken;
|
||||
authorizationBuilder.refreshToken(refreshToken);
|
||||
}
|
||||
@@ -191,6 +222,11 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
|
||||
"The token generator failed to generate the ID token.", ERROR_URI);
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Generated id token");
|
||||
}
|
||||
|
||||
idToken = new OidcIdToken(generatedIdToken.getTokenValue(), generatedIdToken.getIssuedAt(),
|
||||
generatedIdToken.getExpiresAt(), ((Jwt) generatedIdToken).getClaims());
|
||||
authorizationBuilder.token(idToken, (metadata) ->
|
||||
@@ -206,12 +242,20 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
|
||||
|
||||
this.authorizationService.save(authorization);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Saved authorization");
|
||||
}
|
||||
|
||||
Map<String, Object> additionalParameters = Collections.emptyMap();
|
||||
if (idToken != null) {
|
||||
additionalParameters = new HashMap<>();
|
||||
additionalParameters.put(OidcParameterNames.ID_TOKEN, idToken.getTokenValue());
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Authenticated token request");
|
||||
}
|
||||
|
||||
return new OAuth2AccessTokenAuthenticationToken(
|
||||
registeredClient, clientPrincipal, accessToken, refreshToken, additionalParameters);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ import java.util.Base64;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -69,6 +72,7 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
|
||||
private static final String PKCE_ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc7636#section-4.4.1";
|
||||
private static final StringKeyGenerator DEFAULT_STATE_GENERATOR =
|
||||
new Base64StringKeyGenerator(Base64.getUrlEncoder());
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final RegisteredClientRepository registeredClientRepository;
|
||||
private final OAuth2AuthorizationService authorizationService;
|
||||
private final OAuth2AuthorizationConsentService authorizationConsentService;
|
||||
@@ -105,6 +109,10 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
|
||||
authorizationCodeRequestAuthentication, null);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved registered client");
|
||||
}
|
||||
|
||||
OAuth2AuthorizationCodeRequestAuthenticationContext authenticationContext =
|
||||
OAuth2AuthorizationCodeRequestAuthenticationContext.with(authorizationCodeRequestAuthentication)
|
||||
.registeredClient(registeredClient)
|
||||
@@ -129,12 +137,19 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
|
||||
authorizationCodeRequestAuthentication, registeredClient, null);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Validated authorization code request parameters");
|
||||
}
|
||||
|
||||
// ---------------
|
||||
// The request is valid - ensure the resource owner is authenticated
|
||||
// ---------------
|
||||
|
||||
Authentication principal = (Authentication) authorizationCodeRequestAuthentication.getPrincipal();
|
||||
if (!isPrincipalAuthenticated(principal)) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Did not authenticate authorization code request since principal not authenticated");
|
||||
}
|
||||
// Return the authorization request as-is where isAuthenticated() is false
|
||||
return authorizationCodeRequestAuthentication;
|
||||
}
|
||||
@@ -156,11 +171,20 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
|
||||
OAuth2Authorization authorization = authorizationBuilder(registeredClient, principal, authorizationRequest)
|
||||
.attribute(OAuth2ParameterNames.STATE, state)
|
||||
.build();
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
logger.trace("Generated authorization consent state");
|
||||
}
|
||||
|
||||
this.authorizationService.save(authorization);
|
||||
|
||||
Set<String> currentAuthorizedScopes = currentAuthorizationConsent != null ?
|
||||
currentAuthorizationConsent.getScopes() : null;
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Saved authorization");
|
||||
}
|
||||
|
||||
return new OAuth2AuthorizationConsentAuthenticationToken(authorizationRequest.getAuthorizationUri(),
|
||||
registeredClient.getClientId(), principal, state, currentAuthorizedScopes, null);
|
||||
}
|
||||
@@ -174,17 +198,29 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
|
||||
throw new OAuth2AuthorizationCodeRequestAuthenticationException(error, null);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Generated authorization code");
|
||||
}
|
||||
|
||||
OAuth2Authorization authorization = authorizationBuilder(registeredClient, principal, authorizationRequest)
|
||||
.authorizedScopes(authorizationRequest.getScopes())
|
||||
.token(authorizationCode)
|
||||
.build();
|
||||
this.authorizationService.save(authorization);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Saved authorization");
|
||||
}
|
||||
|
||||
String redirectUri = authorizationRequest.getRedirectUri();
|
||||
if (!StringUtils.hasText(redirectUri)) {
|
||||
redirectUri = registeredClient.getRedirectUris().iterator().next();
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Authenticated authorization code request");
|
||||
}
|
||||
|
||||
return new OAuth2AuthorizationCodeRequestAuthenticationToken(authorizationRequest.getAuthorizationUri(),
|
||||
registeredClient.getClientId(), principal, authorizationCode, redirectUri,
|
||||
authorizationRequest.getState(), authorizationRequest.getScopes());
|
||||
|
||||
@@ -20,6 +20,9 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -62,6 +65,7 @@ import org.springframework.util.StringUtils;
|
||||
public final class OAuth2AuthorizationConsentAuthenticationProvider implements AuthenticationProvider {
|
||||
private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1";
|
||||
private static final OAuth2TokenType STATE_TOKEN_TYPE = new OAuth2TokenType(OAuth2ParameterNames.STATE);
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final RegisteredClientRepository registeredClientRepository;
|
||||
private final OAuth2AuthorizationService authorizationService;
|
||||
private final OAuth2AuthorizationConsentService authorizationConsentService;
|
||||
@@ -97,6 +101,10 @@ public final class OAuth2AuthorizationConsentAuthenticationProvider implements A
|
||||
authorizationConsentAuthentication, null, null);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved authorization with authorization consent state");
|
||||
}
|
||||
|
||||
// The 'in-flight' authorization must be associated to the current principal
|
||||
Authentication principal = (Authentication) authorizationConsentAuthentication.getPrincipal();
|
||||
if (!isPrincipalAuthenticated(principal) || !principal.getName().equals(authorization.getPrincipalName())) {
|
||||
@@ -111,6 +119,10 @@ public final class OAuth2AuthorizationConsentAuthenticationProvider implements A
|
||||
authorizationConsentAuthentication, registeredClient, null);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved registered client");
|
||||
}
|
||||
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(OAuth2AuthorizationRequest.class.getName());
|
||||
Set<String> requestedScopes = authorizationRequest.getScopes();
|
||||
Set<String> authorizedScopes = new HashSet<>(authorizationConsentAuthentication.getScopes());
|
||||
@@ -119,6 +131,10 @@ public final class OAuth2AuthorizationConsentAuthenticationProvider implements A
|
||||
authorizationConsentAuthentication, registeredClient, authorizationRequest);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Validated authorization consent request parameters");
|
||||
}
|
||||
|
||||
OAuth2AuthorizationConsent currentAuthorizationConsent = this.authorizationConsentService.findById(
|
||||
authorization.getRegisteredClientId(), authorization.getPrincipalName());
|
||||
Set<String> currentAuthorizedScopes = currentAuthorizationConsent != null ?
|
||||
@@ -139,6 +155,9 @@ public final class OAuth2AuthorizationConsentAuthenticationProvider implements A
|
||||
|
||||
OAuth2AuthorizationConsent.Builder authorizationConsentBuilder;
|
||||
if (currentAuthorizationConsent != null) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved existing authorization consent");
|
||||
}
|
||||
authorizationConsentBuilder = OAuth2AuthorizationConsent.from(currentAuthorizationConsent);
|
||||
} else {
|
||||
authorizationConsentBuilder = OAuth2AuthorizationConsent.withId(
|
||||
@@ -157,6 +176,9 @@ public final class OAuth2AuthorizationConsentAuthenticationProvider implements A
|
||||
.build();
|
||||
// @formatter:on
|
||||
this.authorizationConsentCustomizer.accept(authorizationConsentAuthenticationContext);
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Customized authorization consent");
|
||||
}
|
||||
}
|
||||
|
||||
Set<GrantedAuthority> authorities = new HashSet<>();
|
||||
@@ -166,8 +188,14 @@ public final class OAuth2AuthorizationConsentAuthenticationProvider implements A
|
||||
// Authorization consent denied (or revoked)
|
||||
if (currentAuthorizationConsent != null) {
|
||||
this.authorizationConsentService.remove(currentAuthorizationConsent);
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Revoked authorization consent");
|
||||
}
|
||||
}
|
||||
this.authorizationService.remove(authorization);
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Removed authorization");
|
||||
}
|
||||
throwError(OAuth2ErrorCodes.ACCESS_DENIED, OAuth2ParameterNames.CLIENT_ID,
|
||||
authorizationConsentAuthentication, registeredClient, authorizationRequest);
|
||||
}
|
||||
@@ -175,6 +203,9 @@ public final class OAuth2AuthorizationConsentAuthenticationProvider implements A
|
||||
OAuth2AuthorizationConsent authorizationConsent = authorizationConsentBuilder.build();
|
||||
if (!authorizationConsent.equals(currentAuthorizationConsent)) {
|
||||
this.authorizationConsentService.save(authorizationConsent);
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Saved authorization consent");
|
||||
}
|
||||
}
|
||||
|
||||
OAuth2TokenContext tokenContext = createAuthorizationCodeTokenContext(
|
||||
@@ -186,6 +217,10 @@ public final class OAuth2AuthorizationConsentAuthenticationProvider implements A
|
||||
throw new OAuth2AuthorizationCodeRequestAuthenticationException(error, null);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Generated authorization code");
|
||||
}
|
||||
|
||||
OAuth2Authorization updatedAuthorization = OAuth2Authorization.from(authorization)
|
||||
.authorizedScopes(authorizedScopes)
|
||||
.token(authorizationCode)
|
||||
@@ -195,11 +230,19 @@ public final class OAuth2AuthorizationConsentAuthenticationProvider implements A
|
||||
.build();
|
||||
this.authorizationService.save(updatedAuthorization);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Saved authorization");
|
||||
}
|
||||
|
||||
String redirectUri = authorizationRequest.getRedirectUri();
|
||||
if (!StringUtils.hasText(redirectUri)) {
|
||||
redirectUri = registeredClient.getRedirectUris().iterator().next();
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Authenticated authorization consent request");
|
||||
}
|
||||
|
||||
return new OAuth2AuthorizationCodeRequestAuthenticationToken(
|
||||
authorizationRequest.getAuthorizationUri(), registeredClient.getClientId(), principal, authorizationCode,
|
||||
redirectUri, authorizationRequest.getState(), authorizedScopes);
|
||||
|
||||
@@ -19,6 +19,9 @@ import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@@ -57,6 +60,7 @@ import static org.springframework.security.oauth2.server.authorization.authentic
|
||||
*/
|
||||
public final class OAuth2ClientCredentialsAuthenticationProvider implements AuthenticationProvider {
|
||||
private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2";
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final OAuth2AuthorizationService authorizationService;
|
||||
private final OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator;
|
||||
|
||||
@@ -84,6 +88,10 @@ public final class OAuth2ClientCredentialsAuthenticationProvider implements Auth
|
||||
getAuthenticatedClientElseThrowInvalidClient(clientCredentialsAuthentication);
|
||||
RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved registered client");
|
||||
}
|
||||
|
||||
if (!registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.CLIENT_CREDENTIALS)) {
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT);
|
||||
}
|
||||
@@ -98,6 +106,10 @@ public final class OAuth2ClientCredentialsAuthenticationProvider implements Auth
|
||||
authorizedScopes = new LinkedHashSet<>(clientCredentialsAuthentication.getScopes());
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Validated token request parameters");
|
||||
}
|
||||
|
||||
// @formatter:off
|
||||
OAuth2TokenContext tokenContext = DefaultOAuth2TokenContext.builder()
|
||||
.registeredClient(registeredClient)
|
||||
@@ -116,6 +128,11 @@ public final class OAuth2ClientCredentialsAuthenticationProvider implements Auth
|
||||
"The token generator failed to generate the access token.", ERROR_URI);
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Generated access token");
|
||||
}
|
||||
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(),
|
||||
generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());
|
||||
@@ -137,6 +154,12 @@ public final class OAuth2ClientCredentialsAuthenticationProvider implements Auth
|
||||
|
||||
this.authorizationService.save(authorization);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Saved authorization");
|
||||
// This log is kept separate for consistency with other providers
|
||||
this.logger.trace("Authenticated token request");
|
||||
}
|
||||
|
||||
return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@@ -65,6 +68,7 @@ import static org.springframework.security.oauth2.server.authorization.authentic
|
||||
public final class OAuth2RefreshTokenAuthenticationProvider implements AuthenticationProvider {
|
||||
private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2";
|
||||
private static final OAuth2TokenType ID_TOKEN_TOKEN_TYPE = new OAuth2TokenType(OidcParameterNames.ID_TOKEN);
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final OAuth2AuthorizationService authorizationService;
|
||||
private final OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator;
|
||||
|
||||
@@ -92,12 +96,20 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic
|
||||
getAuthenticatedClientElseThrowInvalidClient(refreshTokenAuthentication);
|
||||
RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved registered client");
|
||||
}
|
||||
|
||||
OAuth2Authorization authorization = this.authorizationService.findByToken(
|
||||
refreshTokenAuthentication.getRefreshToken(), OAuth2TokenType.REFRESH_TOKEN);
|
||||
if (authorization == null) {
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved authorization with refresh token");
|
||||
}
|
||||
|
||||
if (!registeredClient.getId().equals(authorization.getRegisteredClientId())) {
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_CLIENT);
|
||||
}
|
||||
@@ -122,6 +134,11 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic
|
||||
if (!authorizedScopes.containsAll(scopes)) {
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_SCOPE);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Validated token request parameters");
|
||||
}
|
||||
|
||||
if (scopes.isEmpty()) {
|
||||
scopes = authorizedScopes;
|
||||
}
|
||||
@@ -147,6 +164,11 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic
|
||||
"The token generator failed to generate the access token.", ERROR_URI);
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Generated access token");
|
||||
}
|
||||
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(),
|
||||
generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());
|
||||
@@ -169,6 +191,11 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic
|
||||
"The token generator failed to generate the refresh token.", ERROR_URI);
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Generated refresh token");
|
||||
}
|
||||
|
||||
currentRefreshToken = (OAuth2RefreshToken) generatedRefreshToken;
|
||||
authorizationBuilder.refreshToken(currentRefreshToken);
|
||||
}
|
||||
@@ -188,6 +215,11 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic
|
||||
"The token generator failed to generate the ID token.", ERROR_URI);
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Generated id token");
|
||||
}
|
||||
|
||||
idToken = new OidcIdToken(generatedIdToken.getTokenValue(), generatedIdToken.getIssuedAt(),
|
||||
generatedIdToken.getExpiresAt(), ((Jwt) generatedIdToken).getClaims());
|
||||
authorizationBuilder.token(idToken, (metadata) ->
|
||||
@@ -200,12 +232,20 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic
|
||||
|
||||
this.authorizationService.save(authorization);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Saved authorization");
|
||||
}
|
||||
|
||||
Map<String, Object> additionalParameters = Collections.emptyMap();
|
||||
if (idToken != null) {
|
||||
additionalParameters = new HashMap<>();
|
||||
additionalParameters.put(OidcParameterNames.ID_TOKEN, idToken.getTokenValue());
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Authenticated token request");
|
||||
}
|
||||
|
||||
return new OAuth2AccessTokenAuthenticationToken(
|
||||
registeredClient, clientPrincipal, accessToken, currentRefreshToken, additionalParameters);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -53,6 +56,7 @@ public final class OAuth2TokenIntrospectionAuthenticationProvider implements Aut
|
||||
private static final TypeDescriptor OBJECT_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(Object.class);
|
||||
private static final TypeDescriptor LIST_STRING_TYPE_DESCRIPTOR =
|
||||
TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class));
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final RegisteredClientRepository registeredClientRepository;
|
||||
private final OAuth2AuthorizationService authorizationService;
|
||||
|
||||
@@ -81,13 +85,23 @@ public final class OAuth2TokenIntrospectionAuthenticationProvider implements Aut
|
||||
OAuth2Authorization authorization = this.authorizationService.findByToken(
|
||||
tokenIntrospectionAuthentication.getToken(), null);
|
||||
if (authorization == null) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Did not authenticate token introspection request since token was not found");
|
||||
}
|
||||
// Return the authentication request when token not found
|
||||
return tokenIntrospectionAuthentication;
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved authorization with token");
|
||||
}
|
||||
|
||||
OAuth2Authorization.Token<OAuth2Token> authorizedToken =
|
||||
authorization.getToken(tokenIntrospectionAuthentication.getToken());
|
||||
if (!authorizedToken.isActive()) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Did not introspect token since not active");
|
||||
}
|
||||
return new OAuth2TokenIntrospectionAuthenticationToken(tokenIntrospectionAuthentication.getToken(),
|
||||
clientPrincipal, OAuth2TokenIntrospection.builder().build());
|
||||
}
|
||||
@@ -95,6 +109,10 @@ public final class OAuth2TokenIntrospectionAuthenticationProvider implements Aut
|
||||
RegisteredClient authorizedClient = this.registeredClientRepository.findById(authorization.getRegisteredClientId());
|
||||
OAuth2TokenIntrospection tokenClaims = withActiveTokenClaims(authorizedToken, authorizedClient);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Authenticated token introspection request");
|
||||
}
|
||||
|
||||
return new OAuth2TokenIntrospectionAuthenticationToken(authorizedToken.getToken().getTokenValue(),
|
||||
clientPrincipal, tokenClaims);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.security.oauth2.server.authorization.authentication;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@@ -39,6 +42,7 @@ import static org.springframework.security.oauth2.server.authorization.authentic
|
||||
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc7009#section-2.1">Section 2.1 Revocation Request</a>
|
||||
*/
|
||||
public final class OAuth2TokenRevocationAuthenticationProvider implements AuthenticationProvider {
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final OAuth2AuthorizationService authorizationService;
|
||||
|
||||
/**
|
||||
@@ -63,6 +67,9 @@ public final class OAuth2TokenRevocationAuthenticationProvider implements Authen
|
||||
OAuth2Authorization authorization = this.authorizationService.findByToken(
|
||||
tokenRevocationAuthentication.getToken(), null);
|
||||
if (authorization == null) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Did not authenticate token revocation request since token was not found");
|
||||
}
|
||||
// Return the authentication request when token not found
|
||||
return tokenRevocationAuthentication;
|
||||
}
|
||||
@@ -75,6 +82,12 @@ public final class OAuth2TokenRevocationAuthenticationProvider implements Authen
|
||||
authorization = OAuth2AuthenticationProviderUtils.invalidate(authorization, token.getToken());
|
||||
this.authorizationService.save(authorization);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Saved authorization with revoked token");
|
||||
// This log is kept separate for consistency with other providers
|
||||
this.logger.trace("Authenticated token revocation request");
|
||||
}
|
||||
|
||||
return new OAuth2TokenRevocationAuthenticationToken(token.getToken(), clientPrincipal);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.security.oauth2.server.authorization.authentication;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@@ -42,6 +45,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public final class PublicClientAuthenticationProvider implements AuthenticationProvider {
|
||||
private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-3.2.1";
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final RegisteredClientRepository registeredClientRepository;
|
||||
private final CodeVerifierAuthenticator codeVerifierAuthenticator;
|
||||
|
||||
@@ -74,14 +78,26 @@ public final class PublicClientAuthenticationProvider implements AuthenticationP
|
||||
throwInvalidClient(OAuth2ParameterNames.CLIENT_ID);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved registered client");
|
||||
}
|
||||
|
||||
if (!registeredClient.getClientAuthenticationMethods().contains(
|
||||
clientAuthentication.getClientAuthenticationMethod())) {
|
||||
throwInvalidClient("authentication_method");
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Validated client authentication parameters");
|
||||
}
|
||||
|
||||
// Validate the "code_verifier" parameter for the public client
|
||||
this.codeVerifierAuthenticator.authenticateRequired(clientAuthentication, registeredClient);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Authenticated public client");
|
||||
}
|
||||
|
||||
return new OAuth2ClientAuthenticationToken(registeredClient,
|
||||
clientAuthentication.getClientAuthenticationMethod(), null);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -52,6 +55,7 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public final class OidcClientConfigurationAuthenticationProvider implements AuthenticationProvider {
|
||||
static final String DEFAULT_CLIENT_CONFIGURATION_AUTHORIZED_SCOPE = "client.read";
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final RegisteredClientRepository registeredClientRepository;
|
||||
private final OAuth2AuthorizationService authorizationService;
|
||||
private final Converter<RegisteredClient, OidcClientRegistration> clientRegistrationConverter;
|
||||
@@ -98,6 +102,10 @@ public final class OidcClientConfigurationAuthenticationProvider implements Auth
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_TOKEN);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved authorization with access token");
|
||||
}
|
||||
|
||||
OAuth2Authorization.Token<OAuth2AccessToken> authorizedAccessToken = authorization.getAccessToken();
|
||||
if (!authorizedAccessToken.isActive()) {
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_TOKEN);
|
||||
@@ -125,8 +133,16 @@ public final class OidcClientConfigurationAuthenticationProvider implements Auth
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_CLIENT);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Validated client configuration request parameters");
|
||||
}
|
||||
|
||||
OidcClientRegistration clientRegistration = this.clientRegistrationConverter.convert(registeredClient);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Authenticated client configuration request");
|
||||
}
|
||||
|
||||
return new OidcClientRegistrationAuthenticationToken(
|
||||
(Authentication) clientRegistrationAuthentication.getPrincipal(), clientRegistration);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -81,6 +84,7 @@ import org.springframework.util.StringUtils;
|
||||
public final class OidcClientRegistrationAuthenticationProvider implements AuthenticationProvider {
|
||||
private static final String ERROR_URI = "https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError";
|
||||
private static final String DEFAULT_CLIENT_REGISTRATION_AUTHORIZED_SCOPE = "client.create";
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final RegisteredClientRepository registeredClientRepository;
|
||||
private final OAuth2AuthorizationService authorizationService;
|
||||
private final OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator;
|
||||
@@ -134,6 +138,10 @@ public final class OidcClientRegistrationAuthenticationProvider implements Authe
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_TOKEN);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved authorization with initial access token");
|
||||
}
|
||||
|
||||
OAuth2Authorization.Token<OAuth2AccessToken> authorizedAccessToken = authorization.getAccessToken();
|
||||
if (!authorizedAccessToken.isActive()) {
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_TOKEN);
|
||||
@@ -170,9 +178,17 @@ public final class OidcClientRegistrationAuthenticationProvider implements Authe
|
||||
throwInvalidClientRegistration("invalid_client_metadata", OidcClientMetadataClaimNames.TOKEN_ENDPOINT_AUTH_METHOD);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Validated client registration request parameters");
|
||||
}
|
||||
|
||||
RegisteredClient registeredClient = this.registeredClientConverter.convert(clientRegistrationAuthentication.getClientRegistration());
|
||||
this.registeredClientRepository.save(registeredClient);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Saved registered client");
|
||||
}
|
||||
|
||||
OAuth2Authorization registeredClientAuthorization = registerAccessToken(registeredClient);
|
||||
|
||||
// Invalidate the "initial" access token as it can only be used once
|
||||
@@ -182,11 +198,19 @@ public final class OidcClientRegistrationAuthenticationProvider implements Authe
|
||||
}
|
||||
this.authorizationService.save(authorization);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Saved authorization with invalidated initial access token");
|
||||
}
|
||||
|
||||
Map<String, Object> clientRegistrationClaims = this.clientRegistrationConverter.convert(registeredClient).getClaims();
|
||||
OidcClientRegistration clientRegistration = OidcClientRegistration.withClaims(clientRegistrationClaims)
|
||||
.registrationAccessToken(registeredClientAuthorization.getAccessToken().getToken().getTokenValue())
|
||||
.build();
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Authenticated client registration request");
|
||||
}
|
||||
|
||||
return new OidcClientRegistrationAuthenticationToken(
|
||||
(Authentication) clientRegistrationAuthentication.getPrincipal(), clientRegistration);
|
||||
}
|
||||
@@ -216,6 +240,11 @@ public final class OidcClientRegistrationAuthenticationProvider implements Authe
|
||||
"The token generator failed to generate the registration access token.", ERROR_URI);
|
||||
throw new OAuth2AuthenticationException(error);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Generated registration access token");
|
||||
}
|
||||
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
registrationAccessToken.getTokenValue(), registrationAccessToken.getIssuedAt(),
|
||||
registrationAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());
|
||||
@@ -237,6 +266,10 @@ public final class OidcClientRegistrationAuthenticationProvider implements Authe
|
||||
|
||||
this.authorizationService.save(authorization);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Saved authorization with registration access token");
|
||||
}
|
||||
|
||||
return authorization;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@@ -48,6 +51,7 @@ import org.springframework.util.Assert;
|
||||
* @see <a href="https://openid.net/specs/openid-connect-core-1_0.html#UserInfo">5.3. UserInfo Endpoint</a>
|
||||
*/
|
||||
public final class OidcUserInfoAuthenticationProvider implements AuthenticationProvider {
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
private final OAuth2AuthorizationService authorizationService;
|
||||
private Function<OidcUserInfoAuthenticationContext, OidcUserInfo> userInfoMapper = new DefaultOidcUserInfoMapper();
|
||||
|
||||
@@ -82,6 +86,10 @@ public final class OidcUserInfoAuthenticationProvider implements AuthenticationP
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_TOKEN);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Retrieved authorization with access token");
|
||||
}
|
||||
|
||||
OAuth2Authorization.Token<OAuth2AccessToken> authorizedAccessToken = authorization.getAccessToken();
|
||||
if (!authorizedAccessToken.isActive()) {
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_TOKEN);
|
||||
@@ -96,6 +104,10 @@ public final class OidcUserInfoAuthenticationProvider implements AuthenticationP
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_TOKEN);
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Validated user info request");
|
||||
}
|
||||
|
||||
OidcUserInfoAuthenticationContext authenticationContext =
|
||||
OidcUserInfoAuthenticationContext.with(userInfoAuthentication)
|
||||
.accessToken(authorizedAccessToken.getToken())
|
||||
@@ -103,6 +115,10 @@ public final class OidcUserInfoAuthenticationProvider implements AuthenticationP
|
||||
.build();
|
||||
OidcUserInfo userInfo = this.userInfoMapper.apply(authenticationContext);
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Authenticated user info request");
|
||||
}
|
||||
|
||||
return new OidcUserInfoAuthenticationToken(accessTokenAuthentication, userInfo);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
@@ -137,12 +138,18 @@ public final class OidcClientRegistrationEndpointFilter extends OncePerRequestFi
|
||||
|
||||
this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, clientRegistrationAuthenticationResult);
|
||||
} catch (OAuth2AuthenticationException ex) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(LogMessage.format("Client registration request failed: %s", ex.getError()), ex);
|
||||
}
|
||||
this.authenticationFailureHandler.onAuthenticationFailure(request, response, ex);
|
||||
} catch (Exception ex) {
|
||||
OAuth2Error error = new OAuth2Error(
|
||||
OAuth2ErrorCodes.INVALID_REQUEST,
|
||||
"OpenID Connect 1.0 Client Registration Error: " + ex.getMessage(),
|
||||
"https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError");
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(error.getDescription(), ex);
|
||||
}
|
||||
this.authenticationFailureHandler.onAuthenticationFailure(request, response,
|
||||
new OAuth2AuthenticationException(error));
|
||||
} finally {
|
||||
|
||||
@@ -22,6 +22,7 @@ import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
@@ -116,12 +117,18 @@ public final class OidcUserInfoEndpointFilter extends OncePerRequestFilter {
|
||||
|
||||
this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, userInfoAuthenticationResult);
|
||||
} catch (OAuth2AuthenticationException ex) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(LogMessage.format("User info request failed: %s", ex.getError()), ex);
|
||||
}
|
||||
this.authenticationFailureHandler.onAuthenticationFailure(request, response, ex);
|
||||
} catch (Exception ex) {
|
||||
OAuth2Error error = new OAuth2Error(
|
||||
OAuth2ErrorCodes.INVALID_REQUEST,
|
||||
"OpenID Connect 1.0 UserInfo Error: " + ex.getMessage(),
|
||||
"https://openid.net/specs/openid-connect-core-1_0.html#UserInfoError");
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(error.getDescription(), ex);
|
||||
}
|
||||
this.authenticationFailureHandler.onAuthenticationFailure(request, response,
|
||||
new OAuth2AuthenticationException(error));
|
||||
} finally {
|
||||
|
||||
@@ -28,6 +28,7 @@ import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -173,6 +174,9 @@ public final class OAuth2AuthorizationEndpointFilter extends OncePerRequestFilte
|
||||
}
|
||||
|
||||
if (authenticationResult instanceof OAuth2AuthorizationConsentAuthenticationToken) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Authorization consent is required");
|
||||
}
|
||||
sendAuthorizationConsent(request, response,
|
||||
(OAuth2AuthorizationCodeRequestAuthenticationToken) authentication,
|
||||
(OAuth2AuthorizationConsentAuthenticationToken) authenticationResult);
|
||||
@@ -183,6 +187,9 @@ public final class OAuth2AuthorizationEndpointFilter extends OncePerRequestFilte
|
||||
request, response, authenticationResult);
|
||||
|
||||
} catch (OAuth2AuthenticationException ex) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(LogMessage.format("Authorization request failed: %s", ex.getError()), ex);
|
||||
}
|
||||
this.authenticationFailureHandler.onAuthenticationFailure(request, response, ex);
|
||||
}
|
||||
}
|
||||
@@ -260,6 +267,9 @@ public final class OAuth2AuthorizationEndpointFilter extends OncePerRequestFilte
|
||||
.toUriString();
|
||||
this.redirectStrategy.sendRedirect(request, response, redirectUri);
|
||||
} else {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Displaying generated consent screen");
|
||||
}
|
||||
DefaultConsentPage.displayConsent(request, response, clientId, principal, requestedScopes, authorizedScopes, state);
|
||||
}
|
||||
}
|
||||
@@ -316,6 +326,10 @@ public final class OAuth2AuthorizationEndpointFilter extends OncePerRequestFilte
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace("Redirecting to client with error");
|
||||
}
|
||||
|
||||
UriComponentsBuilder uriBuilder = UriComponentsBuilder
|
||||
.fromUriString(authorizationCodeRequestAuthentication.getRedirectUri())
|
||||
.queryParam(OAuth2ParameterNames.ERROR, error.getErrorCode());
|
||||
|
||||
@@ -23,6 +23,7 @@ import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
@@ -123,6 +124,9 @@ public final class OAuth2ClientAuthenticationFilter extends OncePerRequestFilter
|
||||
filterChain.doFilter(request, response);
|
||||
|
||||
} catch (OAuth2AuthenticationException ex) {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(LogMessage.format("Client authentication failed: %s", ex.getError()), ex);
|
||||
}
|
||||
this.authenticationFailureHandler.onAuthenticationFailure(request, response, ex);
|
||||
}
|
||||
}
|
||||
@@ -166,6 +170,10 @@ public final class OAuth2ClientAuthenticationFilter extends OncePerRequestFilter
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
securityContext.setAuthentication(authentication);
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug(LogMessage.format("Set SecurityContextHolder authentication to %s",
|
||||
authentication.getClass().getSimpleName()));
|
||||
}
|
||||
}
|
||||
|
||||
private void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
|
||||
|
||||
@@ -25,6 +25,7 @@ import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
@@ -167,6 +168,9 @@ public final class OAuth2TokenEndpointFilter extends OncePerRequestFilter {
|
||||
this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, accessTokenAuthentication);
|
||||
} catch (OAuth2AuthenticationException ex) {
|
||||
SecurityContextHolder.clearContext();
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(LogMessage.format("Token request failed: %s", ex.getError()), ex);
|
||||
}
|
||||
this.authenticationFailureHandler.onAuthenticationFailure(request, response, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
@@ -113,6 +114,9 @@ public final class OAuth2TokenIntrospectionEndpointFilter extends OncePerRequest
|
||||
this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, tokenIntrospectionAuthenticationResult);
|
||||
} catch (OAuth2AuthenticationException ex) {
|
||||
SecurityContextHolder.clearContext();
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(LogMessage.format("Token introspection request failed: %s", ex.getError()), ex);
|
||||
}
|
||||
this.authenticationFailureHandler.onAuthenticationFailure(request, response, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
@@ -110,6 +111,9 @@ public final class OAuth2TokenRevocationEndpointFilter extends OncePerRequestFil
|
||||
this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, tokenRevocationAuthenticationResult);
|
||||
} catch (OAuth2AuthenticationException ex) {
|
||||
SecurityContextHolder.clearContext();
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(LogMessage.format("Token revocation request failed: %s", ex.getError()), ex);
|
||||
}
|
||||
this.authenticationFailureHandler.onAuthenticationFailure(request, response, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ public class AuthorizationServerConfig {
|
||||
|
||||
@Bean
|
||||
public AuthorizationServerSettings authorizationServerSettings() {
|
||||
return AuthorizationServerSettings.builder().issuer("http://localhost:9000").build();
|
||||
return AuthorizationServerSettings.builder().build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -127,7 +127,7 @@ public class AuthorizationServerConfig {
|
||||
|
||||
@Bean
|
||||
public AuthorizationServerSettings authorizationServerSettings() {
|
||||
return AuthorizationServerSettings.builder().issuer("http://localhost:9000").build();
|
||||
return AuthorizationServerSettings.builder().build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -129,7 +129,7 @@ public class AuthorizationServerConfig {
|
||||
|
||||
@Bean
|
||||
public AuthorizationServerSettings authorizationServerSettings() {
|
||||
return AuthorizationServerSettings.builder().issuer("http://localhost:9000").build();
|
||||
return AuthorizationServerSettings.builder().build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
Reference in New Issue
Block a user