Support resolving issuer from current request
Closes gh-479
This commit is contained in:
@@ -216,9 +216,17 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
|
||||
|
||||
@Override
|
||||
public void configure(B builder) {
|
||||
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
|
||||
|
||||
// IMPORTANT:
|
||||
// This filter must be registered first as it resolves the current issuer identifier and
|
||||
// sets it as a request attribute under WebAttributes.ISSUER, which may be used by upstream components.
|
||||
OAuth2AuthorizationServerMetadataEndpointFilter authorizationServerMetadataEndpointFilter =
|
||||
new OAuth2AuthorizationServerMetadataEndpointFilter(providerSettings);
|
||||
builder.addFilterBefore(postProcess(authorizationServerMetadataEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
|
||||
|
||||
this.configurers.values().forEach(configurer -> configurer.configure(builder));
|
||||
|
||||
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
|
||||
AuthenticationManager authenticationManager = builder.getSharedObject(AuthenticationManager.class);
|
||||
|
||||
OAuth2TokenIntrospectionEndpointFilter tokenIntrospectionEndpointFilter =
|
||||
@@ -238,12 +246,6 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
|
||||
OAuth2ConfigurerUtils.getJwkSource(builder),
|
||||
providerSettings.getJwkSetEndpoint());
|
||||
builder.addFilterBefore(postProcess(jwkSetEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
|
||||
|
||||
if (providerSettings.getIssuer() != null) {
|
||||
OAuth2AuthorizationServerMetadataEndpointFilter authorizationServerMetadataEndpointFilter =
|
||||
new OAuth2AuthorizationServerMetadataEndpointFilter(providerSettings);
|
||||
builder.addFilterBefore(postProcess(authorizationServerMetadataEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Class<? extends AbstractOAuth2Configurer>, AbstractOAuth2Configurer> createConfigurers() {
|
||||
|
||||
@@ -85,16 +85,13 @@ public final class OidcConfigurer extends AbstractOAuth2Configurer {
|
||||
}
|
||||
|
||||
List<RequestMatcher> requestMatchers = new ArrayList<>();
|
||||
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
|
||||
if (providerSettings.getIssuer() != null) {
|
||||
requestMatchers.add(new AntPathRequestMatcher(
|
||||
"/.well-known/openid-configuration", HttpMethod.GET.name()));
|
||||
}
|
||||
requestMatchers.add(new AntPathRequestMatcher(
|
||||
"/.well-known/openid-configuration", HttpMethod.GET.name()));
|
||||
requestMatchers.add(this.userInfoEndpointConfigurer.getRequestMatcher());
|
||||
if (this.clientRegistrationEndpointConfigurer != null) {
|
||||
requestMatchers.add(this.clientRegistrationEndpointConfigurer.getRequestMatcher());
|
||||
}
|
||||
this.requestMatcher = requestMatchers.size() > 1 ? new OrRequestMatcher(requestMatchers) : requestMatchers.get(0);
|
||||
this.requestMatcher = new OrRequestMatcher(requestMatchers);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -105,11 +102,9 @@ public final class OidcConfigurer extends AbstractOAuth2Configurer {
|
||||
}
|
||||
|
||||
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
|
||||
if (providerSettings.getIssuer() != null) {
|
||||
OidcProviderConfigurationEndpointFilter oidcProviderConfigurationEndpointFilter =
|
||||
new OidcProviderConfigurationEndpointFilter(providerSettings);
|
||||
builder.addFilterBefore(postProcess(oidcProviderConfigurationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
|
||||
}
|
||||
OidcProviderConfigurationEndpointFilter oidcProviderConfigurationEndpointFilter =
|
||||
new OidcProviderConfigurationEndpointFilter(providerSettings);
|
||||
builder.addFilterBefore(postProcess(oidcProviderConfigurationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,7 +26,6 @@ import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@@ -87,7 +86,6 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
|
||||
private final JwtEncoder jwtEncoder;
|
||||
private OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer = (context) -> {};
|
||||
private Supplier<String> refreshTokenGenerator = DEFAULT_REFRESH_TOKEN_GENERATOR::generateKey;
|
||||
private ProviderSettings providerSettings;
|
||||
|
||||
/**
|
||||
* Constructs an {@code OAuth2AuthorizationCodeAuthenticationProvider} using the provided parameters.
|
||||
@@ -124,9 +122,8 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
|
||||
this.refreshTokenGenerator = refreshTokenGenerator;
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
@Deprecated
|
||||
protected void setProviderSettings(ProviderSettings providerSettings) {
|
||||
this.providerSettings = providerSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,7 +164,7 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT);
|
||||
}
|
||||
|
||||
String issuer = this.providerSettings != null ? this.providerSettings.getIssuer() : null;
|
||||
String issuer = authorizationCodeAuthentication.getIssuer();
|
||||
Set<String> authorizedScopes = authorization.getAttribute(
|
||||
OAuth2Authorization.AUTHORIZED_SCOPE_ATTRIBUTE_NAME);
|
||||
|
||||
|
||||
@@ -43,7 +43,9 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends OAuth2Authorizat
|
||||
* @param clientPrincipal the authenticated client principal
|
||||
* @param redirectUri the redirect uri
|
||||
* @param additionalParameters the additional parameters
|
||||
* @deprecated Use {@link #OAuth2AuthorizationCodeAuthenticationToken(String, String, Authentication, String, Map)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public OAuth2AuthorizationCodeAuthenticationToken(String code, Authentication clientPrincipal,
|
||||
@Nullable String redirectUri, @Nullable Map<String, Object> additionalParameters) {
|
||||
super(AuthorizationGrantType.AUTHORIZATION_CODE, clientPrincipal, additionalParameters);
|
||||
@@ -52,6 +54,24 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends OAuth2Authorizat
|
||||
this.redirectUri = redirectUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an {@code OAuth2AuthorizationCodeAuthenticationToken} using the provided parameters.
|
||||
*
|
||||
* @param issuer the issuer identifier
|
||||
* @param code the authorization code
|
||||
* @param clientPrincipal the authenticated client principal
|
||||
* @param redirectUri the redirect uri
|
||||
* @param additionalParameters the additional parameters
|
||||
* @since 0.2.1
|
||||
*/
|
||||
public OAuth2AuthorizationCodeAuthenticationToken(String issuer, String code, Authentication clientPrincipal,
|
||||
@Nullable String redirectUri, @Nullable Map<String, Object> additionalParameters) {
|
||||
super(AuthorizationGrantType.AUTHORIZATION_CODE, issuer, clientPrincipal, additionalParameters);
|
||||
Assert.hasText(code, "code cannot be empty");
|
||||
this.code = code;
|
||||
this.redirectUri = redirectUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the authorization code.
|
||||
*
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.springframework.util.Assert;
|
||||
public class OAuth2AuthorizationGrantAuthenticationToken extends AbstractAuthenticationToken {
|
||||
private static final long serialVersionUID = Version.SERIAL_VERSION_UID;
|
||||
private final AuthorizationGrantType authorizationGrantType;
|
||||
private final String issuer;
|
||||
private final Authentication clientPrincipal;
|
||||
private final Map<String, Object> additionalParameters;
|
||||
|
||||
@@ -48,13 +49,40 @@ public class OAuth2AuthorizationGrantAuthenticationToken extends AbstractAuthent
|
||||
* @param authorizationGrantType the authorization grant type
|
||||
* @param clientPrincipal the authenticated client principal
|
||||
* @param additionalParameters the additional parameters
|
||||
* @deprecated Use {@link #OAuth2AuthorizationGrantAuthenticationToken(AuthorizationGrantType, String, Authentication, Map)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
protected OAuth2AuthorizationGrantAuthenticationToken(AuthorizationGrantType authorizationGrantType,
|
||||
Authentication clientPrincipal, @Nullable Map<String, Object> additionalParameters) {
|
||||
super(Collections.emptyList());
|
||||
Assert.notNull(authorizationGrantType, "authorizationGrantType cannot be null");
|
||||
Assert.notNull(clientPrincipal, "clientPrincipal cannot be null");
|
||||
this.authorizationGrantType = authorizationGrantType;
|
||||
this.issuer = null;
|
||||
this.clientPrincipal = clientPrincipal;
|
||||
this.additionalParameters = Collections.unmodifiableMap(
|
||||
additionalParameters != null ?
|
||||
new HashMap<>(additionalParameters) :
|
||||
Collections.emptyMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub-class constructor.
|
||||
*
|
||||
* @param authorizationGrantType the authorization grant type
|
||||
* @param issuer the issuer identifier
|
||||
* @param clientPrincipal the authenticated client principal
|
||||
* @param additionalParameters the additional parameters
|
||||
* @since 0.2.1
|
||||
*/
|
||||
protected OAuth2AuthorizationGrantAuthenticationToken(AuthorizationGrantType authorizationGrantType,
|
||||
String issuer, Authentication clientPrincipal, @Nullable Map<String, Object> additionalParameters) {
|
||||
super(Collections.emptyList());
|
||||
Assert.notNull(authorizationGrantType, "authorizationGrantType cannot be null");
|
||||
Assert.hasText(issuer, "issuer cannot be empty");
|
||||
Assert.notNull(clientPrincipal, "clientPrincipal cannot be null");
|
||||
this.authorizationGrantType = authorizationGrantType;
|
||||
this.issuer = issuer;
|
||||
this.clientPrincipal = clientPrincipal;
|
||||
this.additionalParameters = Collections.unmodifiableMap(
|
||||
additionalParameters != null ?
|
||||
@@ -71,6 +99,16 @@ public class OAuth2AuthorizationGrantAuthenticationToken extends AbstractAuthent
|
||||
return this.authorizationGrantType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the issuer identifier.
|
||||
*
|
||||
* @return the issuer identifier
|
||||
* @since 0.2.1
|
||||
*/
|
||||
public String getIssuer() {
|
||||
return this.issuer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return this.clientPrincipal;
|
||||
|
||||
@@ -19,7 +19,6 @@ import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@@ -62,7 +61,6 @@ public final class OAuth2ClientCredentialsAuthenticationProvider implements Auth
|
||||
private final OAuth2AuthorizationService authorizationService;
|
||||
private final JwtEncoder jwtEncoder;
|
||||
private OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer = (context) -> {};
|
||||
private ProviderSettings providerSettings;
|
||||
|
||||
/**
|
||||
* Constructs an {@code OAuth2ClientCredentialsAuthenticationProvider} using the provided parameters.
|
||||
@@ -90,9 +88,8 @@ public final class OAuth2ClientCredentialsAuthenticationProvider implements Auth
|
||||
this.jwtCustomizer = jwtCustomizer;
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
@Deprecated
|
||||
protected void setProviderSettings(ProviderSettings providerSettings) {
|
||||
this.providerSettings = providerSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -118,7 +115,7 @@ public final class OAuth2ClientCredentialsAuthenticationProvider implements Auth
|
||||
authorizedScopes = new LinkedHashSet<>(clientCredentialsAuthentication.getScopes());
|
||||
}
|
||||
|
||||
String issuer = this.providerSettings != null ? this.providerSettings.getIssuer() : null;
|
||||
String issuer = clientCredentialsAuthentication.getIssuer();
|
||||
|
||||
JoseHeader.Builder headersBuilder = JwtUtils.headers();
|
||||
JwtClaimsSet.Builder claimsBuilder = JwtUtils.accessTokenClaims(
|
||||
|
||||
@@ -41,7 +41,9 @@ public class OAuth2ClientCredentialsAuthenticationToken extends OAuth2Authorizat
|
||||
* @param clientPrincipal the authenticated client principal
|
||||
* @param scopes the requested scope(s)
|
||||
* @param additionalParameters the additional parameters
|
||||
* @deprecated Use {@link #OAuth2ClientCredentialsAuthenticationToken(String, Authentication, Set, Map)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public OAuth2ClientCredentialsAuthenticationToken(Authentication clientPrincipal,
|
||||
@Nullable Set<String> scopes, @Nullable Map<String, Object> additionalParameters) {
|
||||
super(AuthorizationGrantType.CLIENT_CREDENTIALS, clientPrincipal, additionalParameters);
|
||||
@@ -49,6 +51,22 @@ public class OAuth2ClientCredentialsAuthenticationToken extends OAuth2Authorizat
|
||||
scopes != null ? new HashSet<>(scopes) : Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an {@code OAuth2ClientCredentialsAuthenticationToken} using the provided parameters.
|
||||
*
|
||||
* @param issuer the issuer identifier
|
||||
* @param clientPrincipal the authenticated client principal
|
||||
* @param scopes the requested scope(s)
|
||||
* @param additionalParameters the additional parameters
|
||||
* @since 0.2.1
|
||||
*/
|
||||
public OAuth2ClientCredentialsAuthenticationToken(String issuer, Authentication clientPrincipal,
|
||||
@Nullable Set<String> scopes, @Nullable Map<String, Object> additionalParameters) {
|
||||
super(AuthorizationGrantType.CLIENT_CREDENTIALS, issuer, clientPrincipal, additionalParameters);
|
||||
this.scopes = Collections.unmodifiableSet(
|
||||
scopes != null ? new HashSet<>(scopes) : Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the requested scope(s).
|
||||
*
|
||||
|
||||
@@ -26,7 +26,6 @@ import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
@@ -80,7 +79,6 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic
|
||||
private final JwtEncoder jwtEncoder;
|
||||
private OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer = (context) -> {};
|
||||
private Supplier<String> refreshTokenGenerator = DEFAULT_REFRESH_TOKEN_GENERATOR::generateKey;
|
||||
private ProviderSettings providerSettings;
|
||||
|
||||
/**
|
||||
* Constructs an {@code OAuth2RefreshTokenAuthenticationProvider} using the provided parameters.
|
||||
@@ -118,9 +116,8 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic
|
||||
this.refreshTokenGenerator = refreshTokenGenerator;
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
@Deprecated
|
||||
protected void setProviderSettings(ProviderSettings providerSettings) {
|
||||
this.providerSettings = providerSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,7 +163,7 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic
|
||||
scopes = authorizedScopes;
|
||||
}
|
||||
|
||||
String issuer = this.providerSettings != null ? this.providerSettings.getIssuer() : null;
|
||||
String issuer = refreshTokenAuthentication.getIssuer();
|
||||
|
||||
JoseHeader.Builder headersBuilder = JwtUtils.headers();
|
||||
JwtClaimsSet.Builder claimsBuilder = JwtUtils.accessTokenClaims(
|
||||
|
||||
@@ -44,7 +44,9 @@ public class OAuth2RefreshTokenAuthenticationToken extends OAuth2AuthorizationGr
|
||||
* @param clientPrincipal the authenticated client principal
|
||||
* @param scopes the requested scope(s)
|
||||
* @param additionalParameters the additional parameters
|
||||
* @deprecated Use {@link #OAuth2RefreshTokenAuthenticationToken(String, String, Authentication, Set, Map)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public OAuth2RefreshTokenAuthenticationToken(String refreshToken, Authentication clientPrincipal,
|
||||
@Nullable Set<String> scopes, @Nullable Map<String, Object> additionalParameters) {
|
||||
super(AuthorizationGrantType.REFRESH_TOKEN, clientPrincipal, additionalParameters);
|
||||
@@ -54,6 +56,25 @@ public class OAuth2RefreshTokenAuthenticationToken extends OAuth2AuthorizationGr
|
||||
scopes != null ? new HashSet<>(scopes) : Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an {@code OAuth2RefreshTokenAuthenticationToken} using the provided parameters.
|
||||
*
|
||||
* @param issuer the issuer identifier
|
||||
* @param refreshToken the refresh token
|
||||
* @param clientPrincipal the authenticated client principal
|
||||
* @param scopes the requested scope(s)
|
||||
* @param additionalParameters the additional parameters
|
||||
* @since 0.2.1
|
||||
*/
|
||||
public OAuth2RefreshTokenAuthenticationToken(String issuer, String refreshToken, Authentication clientPrincipal,
|
||||
@Nullable Set<String> scopes, @Nullable Map<String, Object> additionalParameters) {
|
||||
super(AuthorizationGrantType.REFRESH_TOKEN, issuer, clientPrincipal, additionalParameters);
|
||||
Assert.hasText(refreshToken, "refreshToken cannot be empty");
|
||||
this.refreshToken = refreshToken;
|
||||
this.scopes = Collections.unmodifiableSet(
|
||||
scopes != null ? new HashSet<>(scopes) : Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the refresh token.
|
||||
*
|
||||
|
||||
@@ -178,9 +178,11 @@ public final class OidcClientRegistrationAuthenticationProvider implements Authe
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_CLIENT);
|
||||
}
|
||||
|
||||
OidcClientRegistration clientRegistration = buildRegistration(registeredClient).build();
|
||||
OidcClientRegistration clientRegistration = buildRegistration(
|
||||
registeredClient, clientRegistrationAuthentication.getIssuer())
|
||||
.build();
|
||||
|
||||
return new OidcClientRegistrationAuthenticationToken(
|
||||
return new OidcClientRegistrationAuthenticationToken(clientRegistrationAuthentication.getIssuer(),
|
||||
(Authentication) clientRegistrationAuthentication.getPrincipal(), clientRegistration);
|
||||
}
|
||||
|
||||
@@ -198,7 +200,8 @@ public final class OidcClientRegistrationAuthenticationProvider implements Authe
|
||||
RegisteredClient registeredClient = createClient(clientRegistrationAuthentication.getClientRegistration());
|
||||
this.registeredClientRepository.save(registeredClient);
|
||||
|
||||
OAuth2Authorization registeredClientAuthorization = registerAccessToken(registeredClient);
|
||||
OAuth2Authorization registeredClientAuthorization = registerAccessToken(
|
||||
registeredClient, clientRegistrationAuthentication.getIssuer());
|
||||
|
||||
// Invalidate the "initial" access token as it can only be used once
|
||||
authorization = OidcAuthenticationProviderUtils.invalidate(authorization, authorizedAccessToken.getToken());
|
||||
@@ -207,21 +210,22 @@ public final class OidcClientRegistrationAuthenticationProvider implements Authe
|
||||
}
|
||||
this.authorizationService.save(authorization);
|
||||
|
||||
OidcClientRegistration clientRegistration = buildRegistration(registeredClient)
|
||||
OidcClientRegistration clientRegistration = buildRegistration(
|
||||
registeredClient, clientRegistrationAuthentication.getIssuer())
|
||||
.registrationAccessToken(registeredClientAuthorization.getAccessToken().getToken().getTokenValue())
|
||||
.build();
|
||||
|
||||
return new OidcClientRegistrationAuthenticationToken(
|
||||
return new OidcClientRegistrationAuthenticationToken(clientRegistrationAuthentication.getIssuer(),
|
||||
(Authentication) clientRegistrationAuthentication.getPrincipal(), clientRegistration);
|
||||
}
|
||||
|
||||
private OAuth2Authorization registerAccessToken(RegisteredClient registeredClient) {
|
||||
private OAuth2Authorization registerAccessToken(RegisteredClient registeredClient, String issuer) {
|
||||
JoseHeader headers = JwtUtils.headers().build();
|
||||
|
||||
Set<String> authorizedScopes = Collections.singleton(DEFAULT_CLIENT_CONFIGURATION_AUTHORIZED_SCOPE);
|
||||
|
||||
JwtClaimsSet claims = JwtUtils.accessTokenClaims(
|
||||
registeredClient, this.providerSettings.getIssuer(), registeredClient.getClientId(), authorizedScopes)
|
||||
registeredClient, issuer, registeredClient.getClientId(), authorizedScopes)
|
||||
.build();
|
||||
|
||||
Jwt registrationAccessToken = this.jwtEncoder.encode(headers, claims);
|
||||
@@ -246,7 +250,7 @@ public final class OidcClientRegistrationAuthenticationProvider implements Authe
|
||||
return registeredClientAuthorization;
|
||||
}
|
||||
|
||||
private OidcClientRegistration.Builder buildRegistration(RegisteredClient registeredClient) {
|
||||
private OidcClientRegistration.Builder buildRegistration(RegisteredClient registeredClient, String issuer) {
|
||||
// @formatter:off
|
||||
OidcClientRegistration.Builder builder = OidcClientRegistration.builder()
|
||||
.clientId(registeredClient.getClientId())
|
||||
@@ -270,7 +274,7 @@ public final class OidcClientRegistrationAuthenticationProvider implements Authe
|
||||
scopes.addAll(registeredClient.getScopes()));
|
||||
}
|
||||
|
||||
String registrationClientUri = UriComponentsBuilder.fromUriString(this.providerSettings.getIssuer())
|
||||
String registrationClientUri = UriComponentsBuilder.fromUriString(issuer)
|
||||
.path(this.providerSettings.getOidcClientRegistrationEndpoint())
|
||||
.queryParam(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId())
|
||||
.toUriString();
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class OidcClientRegistrationAuthenticationToken extends AbstractAuthenticationToken {
|
||||
private static final long serialVersionUID = Version.SERIAL_VERSION_UID;
|
||||
private final String issuer;
|
||||
private final Authentication principal;
|
||||
private final OidcClientRegistration clientRegistration;
|
||||
private final String clientId;
|
||||
@@ -45,11 +46,14 @@ public class OidcClientRegistrationAuthenticationToken extends AbstractAuthentic
|
||||
*
|
||||
* @param principal the authenticated principal
|
||||
* @param clientRegistration the client registration
|
||||
* @deprecated Use {@link #OidcClientRegistrationAuthenticationToken(String, Authentication, OidcClientRegistration)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public OidcClientRegistrationAuthenticationToken(Authentication principal, OidcClientRegistration clientRegistration) {
|
||||
super(Collections.emptyList());
|
||||
Assert.notNull(principal, "principal cannot be null");
|
||||
Assert.notNull(clientRegistration, "clientRegistration cannot be null");
|
||||
this.issuer = null;
|
||||
this.principal = principal;
|
||||
this.clientRegistration = clientRegistration;
|
||||
this.clientId = null;
|
||||
@@ -59,20 +63,53 @@ public class OidcClientRegistrationAuthenticationToken extends AbstractAuthentic
|
||||
/**
|
||||
* Constructs an {@code OidcClientRegistrationAuthenticationToken} using the provided parameters.
|
||||
*
|
||||
* @param issuer the issuer identifier
|
||||
* @param principal the authenticated principal
|
||||
* @param clientRegistration the client registration
|
||||
* @since 0.2.1
|
||||
*/
|
||||
public OidcClientRegistrationAuthenticationToken(String issuer, Authentication principal, OidcClientRegistration clientRegistration) {
|
||||
super(Collections.emptyList());
|
||||
Assert.hasText(issuer, "issuer cannot be empty");
|
||||
Assert.notNull(principal, "principal cannot be null");
|
||||
Assert.notNull(clientRegistration, "clientRegistration cannot be null");
|
||||
this.issuer = issuer;
|
||||
this.principal = principal;
|
||||
this.clientRegistration = clientRegistration;
|
||||
this.clientId = null;
|
||||
setAuthenticated(principal.isAuthenticated());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an {@code OidcClientRegistrationAuthenticationToken} using the provided parameters.
|
||||
*
|
||||
* @param issuer the issuer identifier
|
||||
* @param principal the authenticated principal
|
||||
* @param clientId the client identifier
|
||||
* @since 0.2.1
|
||||
*/
|
||||
public OidcClientRegistrationAuthenticationToken(Authentication principal, String clientId) {
|
||||
public OidcClientRegistrationAuthenticationToken(String issuer, Authentication principal, String clientId) {
|
||||
super(Collections.emptyList());
|
||||
Assert.hasText(issuer, "issuer cannot be empty");
|
||||
Assert.notNull(principal, "principal cannot be null");
|
||||
Assert.hasText(clientId, "clientId cannot be empty");
|
||||
this.issuer = issuer;
|
||||
this.principal = principal;
|
||||
this.clientRegistration = null;
|
||||
this.clientId = clientId;
|
||||
setAuthenticated(principal.isAuthenticated());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the issuer identifier.
|
||||
*
|
||||
* @return the issuer identifier
|
||||
* @since 0.2.1
|
||||
*/
|
||||
public String getIssuer() {
|
||||
return this.issuer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return this.principal;
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMe
|
||||
import org.springframework.security.oauth2.core.oidc.OidcClientRegistration;
|
||||
import org.springframework.security.oauth2.core.oidc.http.converter.OidcClientRegistrationHttpMessageConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.oidc.authentication.OidcClientRegistrationAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.web.WebAttributes;
|
||||
import org.springframework.security.web.util.matcher.AndRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||
@@ -148,7 +149,10 @@ public final class OidcClientRegistrationEndpointFilter extends OncePerRequestFi
|
||||
if ("POST".equals(request.getMethod())) {
|
||||
OidcClientRegistration clientRegistration = this.clientRegistrationHttpMessageConverter.read(
|
||||
OidcClientRegistration.class, new ServletServerHttpRequest(request));
|
||||
return new OidcClientRegistrationAuthenticationToken(principal, clientRegistration);
|
||||
|
||||
String issuer = (String) request.getAttribute(WebAttributes.ISSUER);
|
||||
|
||||
return new OidcClientRegistrationAuthenticationToken(issuer, principal, clientRegistration);
|
||||
}
|
||||
|
||||
// client_id (REQUIRED)
|
||||
@@ -158,7 +162,9 @@ public final class OidcClientRegistrationEndpointFilter extends OncePerRequestFi
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST);
|
||||
}
|
||||
|
||||
return new OidcClientRegistrationAuthenticationToken(principal, clientId);
|
||||
String issuer = (String) request.getAttribute(WebAttributes.ISSUER);
|
||||
|
||||
return new OidcClientRegistrationAuthenticationToken(issuer, principal, clientId);
|
||||
}
|
||||
|
||||
private void sendClientRegistrationResponse(HttpServletResponse response, HttpStatus httpStatus, OidcClientRegistration clientRegistration) throws IOException {
|
||||
|
||||
@@ -15,6 +15,13 @@
|
||||
*/
|
||||
package org.springframework.security.oauth2.server.authorization.oidc.web;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
@@ -26,18 +33,13 @@ import org.springframework.security.oauth2.core.oidc.OidcScopes;
|
||||
import org.springframework.security.oauth2.core.oidc.http.converter.OidcProviderConfigurationHttpMessageConverter;
|
||||
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
|
||||
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.web.WebAttributes;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A {@code Filter} that processes OpenID Provider Configuration Requests.
|
||||
*
|
||||
@@ -76,13 +78,15 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques
|
||||
return;
|
||||
}
|
||||
|
||||
String issuer = (String) request.getAttribute(WebAttributes.ISSUER);
|
||||
|
||||
OidcProviderConfiguration providerConfiguration = OidcProviderConfiguration.builder()
|
||||
.issuer(this.providerSettings.getIssuer())
|
||||
.authorizationEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getAuthorizationEndpoint()))
|
||||
.tokenEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getTokenEndpoint()))
|
||||
.issuer(issuer)
|
||||
.authorizationEndpoint(asUrl(issuer, this.providerSettings.getAuthorizationEndpoint()))
|
||||
.tokenEndpoint(asUrl(issuer, this.providerSettings.getTokenEndpoint()))
|
||||
.tokenEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue())
|
||||
.tokenEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST.getValue())
|
||||
.jwkSetUrl(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getJwkSetEndpoint()))
|
||||
.jwkSetUrl(asUrl(issuer, this.providerSettings.getJwkSetEndpoint()))
|
||||
.responseType(OAuth2AuthorizationResponseType.CODE.getValue())
|
||||
.grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue())
|
||||
.grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
|
||||
@@ -100,4 +104,5 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques
|
||||
private static String asUrl(String issuer, String endpoint) {
|
||||
return UriComponentsBuilder.fromUriString(issuer).path(endpoint).build().toUriString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.security.oauth2.core.OAuth2AuthorizationServerMetadat
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType;
|
||||
import org.springframework.security.oauth2.core.http.converter.OAuth2AuthorizationServerMetadataHttpMessageConverter;
|
||||
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
|
||||
import org.springframework.security.web.util.UrlUtils;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -43,6 +44,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
* A {@code Filter} that processes OAuth 2.0 Authorization Server Metadata Requests.
|
||||
*
|
||||
* @author Daniel Garnier-Moiroux
|
||||
* @author Joe Grandja
|
||||
* @since 0.1.1
|
||||
* @see OAuth2AuthorizationServerMetadata
|
||||
* @see ProviderSettings
|
||||
@@ -72,24 +74,32 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
// Resolve the current issuer identifier
|
||||
String issuer = this.providerSettings.getIssuer();
|
||||
if (issuer == null) {
|
||||
issuer = resolveIssuer(request);
|
||||
}
|
||||
// Set the current issuer identifier as a request attribute (for use by upstream components)
|
||||
request.setAttribute(WebAttributes.ISSUER, issuer);
|
||||
|
||||
if (!this.requestMatcher.matches(request)) {
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
OAuth2AuthorizationServerMetadata authorizationServerMetadata = OAuth2AuthorizationServerMetadata.builder()
|
||||
.issuer(this.providerSettings.getIssuer())
|
||||
.authorizationEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getAuthorizationEndpoint()))
|
||||
.tokenEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getTokenEndpoint()))
|
||||
.issuer(issuer)
|
||||
.authorizationEndpoint(asUrl(issuer, this.providerSettings.getAuthorizationEndpoint()))
|
||||
.tokenEndpoint(asUrl(issuer, this.providerSettings.getTokenEndpoint()))
|
||||
.tokenEndpointAuthenticationMethods(clientAuthenticationMethods())
|
||||
.jwkSetUrl(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getJwkSetEndpoint()))
|
||||
.jwkSetUrl(asUrl(issuer, this.providerSettings.getJwkSetEndpoint()))
|
||||
.responseType(OAuth2AuthorizationResponseType.CODE.getValue())
|
||||
.grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue())
|
||||
.grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
|
||||
.grantType(AuthorizationGrantType.REFRESH_TOKEN.getValue())
|
||||
.tokenRevocationEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getTokenRevocationEndpoint()))
|
||||
.tokenRevocationEndpoint(asUrl(issuer, this.providerSettings.getTokenRevocationEndpoint()))
|
||||
.tokenRevocationEndpointAuthenticationMethods(clientAuthenticationMethods())
|
||||
.tokenIntrospectionEndpoint(asUrl(this.providerSettings.getIssuer(), this.providerSettings.getTokenIntrospectionEndpoint()))
|
||||
.tokenIntrospectionEndpoint(asUrl(issuer, this.providerSettings.getTokenIntrospectionEndpoint()))
|
||||
.tokenIntrospectionEndpointAuthenticationMethods(clientAuthenticationMethods())
|
||||
.codeChallengeMethod("plain")
|
||||
.codeChallengeMethod("S256")
|
||||
@@ -100,6 +110,17 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP
|
||||
authorizationServerMetadata, MediaType.APPLICATION_JSON, httpResponse);
|
||||
}
|
||||
|
||||
private static String resolveIssuer(HttpServletRequest request) {
|
||||
// @formatter:off
|
||||
return UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request))
|
||||
.replacePath(request.getContextPath())
|
||||
.replaceQuery(null)
|
||||
.fragment(null)
|
||||
.build()
|
||||
.toUriString();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static Consumer<List<String>> clientAuthenticationMethods() {
|
||||
return (authenticationMethods) -> {
|
||||
authenticationMethods.add(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue());
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2020-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.oauth2.server.authorization.web;
|
||||
|
||||
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
|
||||
|
||||
/**
|
||||
* Well-known attribute names which are used to store information in request or session scope.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 0.2.1
|
||||
*/
|
||||
public final class WebAttributes {
|
||||
|
||||
private WebAttributes() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link javax.servlet.http.HttpServletRequest#getAttribute(String) request attribute} name that holds the current issuer identifier.
|
||||
* The issuer identifier is resolved from {@link ProviderSettings#getIssuer()} or dynamically from the current {@link javax.servlet.http.HttpServletRequest}.
|
||||
*/
|
||||
public static final String ISSUER = WebAttributes.class.getName().concat(".ISSUER");
|
||||
|
||||
}
|
||||
@@ -28,6 +28,7 @@ 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.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.WebAttributes;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -88,8 +89,10 @@ public final class OAuth2AuthorizationCodeAuthenticationConverter implements Aut
|
||||
}
|
||||
});
|
||||
|
||||
String issuer = (String) request.getAttribute(WebAttributes.ISSUER);
|
||||
|
||||
return new OAuth2AuthorizationCodeAuthenticationToken(
|
||||
code, clientPrincipal, redirectUri, additionalParameters);
|
||||
issuer, code, clientPrincipal, redirectUri, additionalParameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
||||
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.WebAttributes;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -83,7 +84,10 @@ public final class OAuth2ClientCredentialsAuthenticationConverter implements Aut
|
||||
}
|
||||
});
|
||||
|
||||
String issuer = (String) request.getAttribute(WebAttributes.ISSUER);
|
||||
|
||||
return new OAuth2ClientCredentialsAuthenticationToken(
|
||||
clientPrincipal, requestedScopes, additionalParameters);
|
||||
issuer, clientPrincipal, requestedScopes, additionalParameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ 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.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter;
|
||||
import org.springframework.security.oauth2.server.authorization.web.WebAttributes;
|
||||
import org.springframework.security.web.authentication.AuthenticationConverter;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -94,7 +95,10 @@ public final class OAuth2RefreshTokenAuthenticationConverter implements Authenti
|
||||
}
|
||||
});
|
||||
|
||||
String issuer = (String) request.getAttribute(WebAttributes.ISSUER);
|
||||
|
||||
return new OAuth2RefreshTokenAuthenticationToken(
|
||||
refreshToken, clientPrincipal, requestedScopes, additionalParameters);
|
||||
issuer, refreshToken, clientPrincipal, requestedScopes, additionalParameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -213,10 +213,11 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
|
||||
this.registeredClientRepository.save(registeredClient);
|
||||
|
||||
String issuer = "https://example.com/issuer1";
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication =
|
||||
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
|
||||
new OAuth2ClientCredentialsAuthenticationToken(issuer, clientPrincipal, null, null);
|
||||
when(authenticationConverter.convert(any())).thenReturn(clientCredentialsAuthentication);
|
||||
|
||||
OAuth2AccessToken accessToken = new OAuth2AccessToken(
|
||||
|
||||
@@ -88,9 +88,10 @@ public class JwtEncodingContextTests {
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
String issuer = "https://provider.com";
|
||||
OAuth2AuthorizationCodeAuthenticationToken authorizationGrant =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(
|
||||
"code", clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
issuer, "code", clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
|
||||
JwtEncodingContext context = JwtEncodingContext.with(headers, claims)
|
||||
.registeredClient(registeredClient)
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthorizationCode;
|
||||
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenType;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
@@ -48,7 +49,6 @@ import org.springframework.security.oauth2.jwt.JwtClaimsSet;
|
||||
import org.springframework.security.oauth2.jwt.JwtEncoder;
|
||||
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthorizationCode;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
|
||||
import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
|
||||
@@ -74,6 +74,7 @@ import static org.mockito.Mockito.when;
|
||||
* @author Daniel Garnier-Moiroux
|
||||
*/
|
||||
public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
private static final String ISSUER = "https://example.com/issuer1";
|
||||
private static final String AUTHORIZATION_CODE = "code";
|
||||
private static final OAuth2TokenType AUTHORIZATION_CODE_TOKEN_TYPE = new OAuth2TokenType(OAuth2ParameterNames.CODE);
|
||||
private OAuth2AuthorizationService authorizationService;
|
||||
@@ -130,7 +131,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
TestingAuthenticationToken clientPrincipal = new TestingAuthenticationToken(
|
||||
registeredClient.getClientId(), registeredClient.getClientSecret());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, null, null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(ISSUER, AUTHORIZATION_CODE, clientPrincipal, null, null);
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
|
||||
@@ -144,7 +145,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient.getClientId(), ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret(), null);
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, null, null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(ISSUER, AUTHORIZATION_CODE, clientPrincipal, null, null);
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
|
||||
@@ -158,7 +159,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, null, null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(ISSUER, AUTHORIZATION_CODE, clientPrincipal, null, null);
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
|
||||
@@ -176,7 +177,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, null, null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(ISSUER, AUTHORIZATION_CODE, clientPrincipal, null, null);
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
|
||||
@@ -203,7 +204,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri() + "-invalid", null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(ISSUER, AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri() + "-invalid", null);
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
.extracting(ex -> ((OAuth2AuthenticationException) ex).getError())
|
||||
@@ -227,7 +228,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(ISSUER, AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -253,7 +254,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(ISSUER, AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -274,7 +275,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(ISSUER, AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
|
||||
when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt());
|
||||
|
||||
@@ -330,7 +331,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(ISSUER, AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
|
||||
when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt());
|
||||
|
||||
@@ -404,7 +405,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(ISSUER, AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
|
||||
when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt());
|
||||
|
||||
@@ -467,7 +468,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(ISSUER, AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
|
||||
Instant accessTokenIssuedAt = Instant.now();
|
||||
Instant accessTokenExpiresAt = accessTokenIssuedAt.plus(accessTokenTTL);
|
||||
@@ -506,7 +507,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(ISSUER, AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
|
||||
when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt());
|
||||
|
||||
@@ -539,7 +540,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
|
||||
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
|
||||
OAuth2AuthorizationRequest.class.getName());
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(ISSUER, AUTHORIZATION_CODE, clientPrincipal, authorizationRequest.getRedirectUri(), null);
|
||||
|
||||
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
|
||||
(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
|
||||
|
||||
@@ -35,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
* @author Daniel Garnier-Moiroux
|
||||
*/
|
||||
public class OAuth2AuthorizationCodeAuthenticationTokenTests {
|
||||
private String issuer = "https://example.com/issuer1";
|
||||
private String code = "code";
|
||||
private RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
private OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
@@ -42,16 +43,23 @@ public class OAuth2AuthorizationCodeAuthenticationTokenTests {
|
||||
private String redirectUri = "redirectUri";
|
||||
private Map<String, Object> additionalParameters = Collections.singletonMap("param1", "value1");
|
||||
|
||||
@Test
|
||||
public void constructorWhenIssuerNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> new OAuth2AuthorizationCodeAuthenticationToken(null, this.code, this.clientPrincipal, this.redirectUri, null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("issuer cannot be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenCodeNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> new OAuth2AuthorizationCodeAuthenticationToken(null, this.clientPrincipal, this.redirectUri, null))
|
||||
assertThatThrownBy(() -> new OAuth2AuthorizationCodeAuthenticationToken(this.issuer, null, this.clientPrincipal, this.redirectUri, null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("code cannot be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenClientPrincipalNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> new OAuth2AuthorizationCodeAuthenticationToken(this.code, null, this.redirectUri, null))
|
||||
assertThatThrownBy(() -> new OAuth2AuthorizationCodeAuthenticationToken(this.issuer, this.code, null, this.redirectUri, null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("clientPrincipal cannot be null");
|
||||
}
|
||||
@@ -59,8 +67,9 @@ public class OAuth2AuthorizationCodeAuthenticationTokenTests {
|
||||
@Test
|
||||
public void constructorWhenClientPrincipalProvidedThenCreated() {
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication = new OAuth2AuthorizationCodeAuthenticationToken(
|
||||
this.code, this.clientPrincipal, this.redirectUri, this.additionalParameters);
|
||||
this.issuer, this.code, this.clientPrincipal, this.redirectUri, this.additionalParameters);
|
||||
assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
|
||||
assertThat(authentication.getIssuer()).isEqualTo(this.issuer);
|
||||
assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal);
|
||||
assertThat(authentication.getCredentials().toString()).isEmpty();
|
||||
assertThat(authentication.getCode()).isEqualTo(this.code);
|
||||
@@ -71,7 +80,7 @@ public class OAuth2AuthorizationCodeAuthenticationTokenTests {
|
||||
@Test
|
||||
public void getAdditionalParametersWhenUpdateThenThrowUnsupportedOperationException() {
|
||||
OAuth2AuthorizationCodeAuthenticationToken authentication = new OAuth2AuthorizationCodeAuthenticationToken(
|
||||
this.code, this.clientPrincipal, this.redirectUri, this.additionalParameters);
|
||||
this.issuer, this.code, this.clientPrincipal, this.redirectUri, this.additionalParameters);
|
||||
assertThatThrownBy(() -> authentication.getAdditionalParameters().put("another_key", 1))
|
||||
.isInstanceOf(UnsupportedOperationException.class);
|
||||
assertThatThrownBy(() -> authentication.getAdditionalParameters().remove("some_key"))
|
||||
|
||||
@@ -36,12 +36,12 @@ import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
|
||||
import org.springframework.security.oauth2.jwt.JoseHeaderNames;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.jwt.JwtEncoder;
|
||||
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
|
||||
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
@@ -105,11 +105,12 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientPrincipalNotOAuth2ClientAuthenticationTokenThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
|
||||
TestingAuthenticationToken clientPrincipal = new TestingAuthenticationToken(
|
||||
registeredClient.getClientId(), registeredClient.getClientSecret());
|
||||
OAuth2ClientCredentialsAuthenticationToken authentication =
|
||||
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
|
||||
new OAuth2ClientCredentialsAuthenticationToken(issuer, clientPrincipal, null, null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -120,11 +121,12 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientPrincipalNotAuthenticatedThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient.getClientId(), ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret(), null);
|
||||
OAuth2ClientCredentialsAuthenticationToken authentication =
|
||||
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
|
||||
new OAuth2ClientCredentialsAuthenticationToken(issuer, clientPrincipal, null, null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -135,13 +137,14 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientNotAuthorizedToRequestTokenThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2()
|
||||
.authorizationGrantTypes(grantTypes -> grantTypes.remove(AuthorizationGrantType.CLIENT_CREDENTIALS))
|
||||
.build();
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2ClientCredentialsAuthenticationToken authentication =
|
||||
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
|
||||
new OAuth2ClientCredentialsAuthenticationToken(issuer, clientPrincipal, null, null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -152,11 +155,12 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenInvalidScopeThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2ClientCredentialsAuthenticationToken authentication = new OAuth2ClientCredentialsAuthenticationToken(
|
||||
clientPrincipal, Collections.singleton("invalid-scope"), null);
|
||||
issuer, clientPrincipal, Collections.singleton("invalid-scope"), null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -167,12 +171,13 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenScopeRequestedThenAccessTokenContainsScope() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
Set<String> requestedScope = Collections.singleton("scope1");
|
||||
OAuth2ClientCredentialsAuthenticationToken authentication =
|
||||
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, requestedScope, null);
|
||||
new OAuth2ClientCredentialsAuthenticationToken(issuer, clientPrincipal, requestedScope, null);
|
||||
|
||||
when(this.jwtEncoder.encode(any(), any()))
|
||||
.thenReturn(createJwt(Collections.singleton("mapped-scoped")));
|
||||
@@ -184,11 +189,12 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenValidAuthenticationThenReturnAccessToken() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2ClientCredentialsAuthenticationToken authentication =
|
||||
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
|
||||
new OAuth2ClientCredentialsAuthenticationToken(issuer, clientPrincipal, null, null);
|
||||
|
||||
when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt(registeredClient.getScopes()));
|
||||
|
||||
|
||||
@@ -35,15 +35,23 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
* @author Alexey Nesterov
|
||||
*/
|
||||
public class OAuth2ClientCredentialsAuthenticationTokenTests {
|
||||
private String issuer = "https://example.com/issuer1";
|
||||
private final RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
private final OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret());
|
||||
private Set<String> scopes = Collections.singleton("scope1");
|
||||
private Map<String, Object> additionalParameters = Collections.singletonMap("param1", "value1");
|
||||
|
||||
@Test
|
||||
public void constructorWhenIssuerNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> new OAuth2ClientCredentialsAuthenticationToken(null, this.clientPrincipal, this.scopes, this.additionalParameters))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("issuer cannot be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenClientPrincipalNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> new OAuth2ClientCredentialsAuthenticationToken(null, this.scopes, this.additionalParameters))
|
||||
assertThatThrownBy(() -> new OAuth2ClientCredentialsAuthenticationToken(this.issuer, null, this.scopes, this.additionalParameters))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("clientPrincipal cannot be null");
|
||||
}
|
||||
@@ -51,9 +59,10 @@ public class OAuth2ClientCredentialsAuthenticationTokenTests {
|
||||
@Test
|
||||
public void constructorWhenClientPrincipalProvidedThenCreated() {
|
||||
OAuth2ClientCredentialsAuthenticationToken authentication = new OAuth2ClientCredentialsAuthenticationToken(
|
||||
this.clientPrincipal, this.scopes, this.additionalParameters);
|
||||
this.issuer, this.clientPrincipal, this.scopes, this.additionalParameters);
|
||||
|
||||
assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.CLIENT_CREDENTIALS);
|
||||
assertThat(authentication.getIssuer()).isEqualTo(this.issuer);
|
||||
assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal);
|
||||
assertThat(authentication.getCredentials().toString()).isEmpty();
|
||||
assertThat(authentication.getScopes()).isEqualTo(this.scopes);
|
||||
@@ -65,9 +74,10 @@ public class OAuth2ClientCredentialsAuthenticationTokenTests {
|
||||
Set<String> expectedScopes = Collections.singleton("test-scope");
|
||||
|
||||
OAuth2ClientCredentialsAuthenticationToken authentication = new OAuth2ClientCredentialsAuthenticationToken(
|
||||
this.clientPrincipal, expectedScopes, this.additionalParameters);
|
||||
this.issuer, this.clientPrincipal, expectedScopes, this.additionalParameters);
|
||||
|
||||
assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.CLIENT_CREDENTIALS);
|
||||
assertThat(authentication.getIssuer()).isEqualTo(this.issuer);
|
||||
assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal);
|
||||
assertThat(authentication.getCredentials().toString()).isEmpty();
|
||||
assertThat(authentication.getScopes()).isEqualTo(expectedScopes);
|
||||
|
||||
@@ -132,6 +132,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenValidRefreshTokenThenReturnAccessToken() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();
|
||||
when(this.authorizationService.findByToken(
|
||||
@@ -142,7 +143,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
issuer, authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
|
||||
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
|
||||
(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
|
||||
@@ -176,6 +177,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenValidRefreshTokenThenReturnIdToken() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().scope(OidcScopes.OPENID).build();
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();
|
||||
when(this.authorizationService.findByToken(
|
||||
@@ -186,7 +188,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
issuer, authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
|
||||
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
|
||||
(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
|
||||
@@ -243,6 +245,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenReuseRefreshTokensFalseThenReturnNewRefreshToken() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
|
||||
.tokenSettings(TokenSettings.builder().reuseRefreshTokens(false).build())
|
||||
.build();
|
||||
@@ -255,7 +258,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
issuer, authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
|
||||
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
|
||||
(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
|
||||
@@ -270,6 +273,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenRequestedScopesAuthorizedThenAccessTokenIncludesScopes() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
|
||||
.scope("scope2")
|
||||
.scope("scope3")
|
||||
@@ -286,7 +290,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
Set<String> requestedScopes = new HashSet<>(authorizedScopes);
|
||||
requestedScopes.remove("scope1");
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, requestedScopes, null);
|
||||
issuer, authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, requestedScopes, null);
|
||||
|
||||
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
|
||||
(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
|
||||
@@ -296,6 +300,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenCustomRefreshTokenGeneratorThenUsed() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
|
||||
.tokenSettings(TokenSettings.builder().reuseRefreshTokens(false).build())
|
||||
.build();
|
||||
@@ -317,7 +322,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
issuer, authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
|
||||
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
|
||||
(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
|
||||
@@ -328,6 +333,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenRequestedScopesNotAuthorizedThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();
|
||||
when(this.authorizationService.findByToken(
|
||||
@@ -341,7 +347,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
Set<String> requestedScopes = new HashSet<>(authorizedScopes);
|
||||
requestedScopes.add("unauthorized");
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, requestedScopes, null);
|
||||
issuer, authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, requestedScopes, null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -352,11 +358,12 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenInvalidRefreshTokenThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
"invalid", clientPrincipal, null, null);
|
||||
issuer, "invalid", clientPrincipal, null, null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -367,11 +374,12 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientPrincipalNotOAuth2ClientAuthenticationTokenThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
TestingAuthenticationToken clientPrincipal = new TestingAuthenticationToken(
|
||||
registeredClient.getClientId(), registeredClient.getClientSecret());
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
"refresh-token", clientPrincipal, null, null);
|
||||
issuer, "refresh-token", clientPrincipal, null, null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -382,11 +390,12 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientPrincipalNotAuthenticatedThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient.getClientId(), ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret(), null);
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
"refresh-token", clientPrincipal, null, null);
|
||||
issuer, "refresh-token", clientPrincipal, null, null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -397,6 +406,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenRefreshTokenIssuedToAnotherClientThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();
|
||||
when(this.authorizationService.findByToken(
|
||||
@@ -408,7 +418,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient2, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient2.getClientSecret());
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
issuer, authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -419,6 +429,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientNotAuthorizedToRefreshTokenThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient()
|
||||
.authorizationGrantTypes(grantTypes -> grantTypes.remove(AuthorizationGrantType.REFRESH_TOKEN))
|
||||
.build();
|
||||
@@ -431,7 +442,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
issuer, authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -442,6 +453,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenExpiredRefreshTokenThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();
|
||||
OAuth2RefreshToken expiredRefreshToken = new OAuth2RefreshToken(
|
||||
@@ -455,7 +467,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
issuer, authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -466,6 +478,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenRevokedRefreshTokenThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
OAuth2RefreshToken refreshToken = new OAuth2RefreshToken(
|
||||
"refresh-token", Instant.now().minusSeconds(120), Instant.now().plusSeconds(1000));
|
||||
@@ -480,7 +493,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
|
||||
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
issuer, authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
|
||||
@@ -36,25 +36,33 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
* @since 0.0.3
|
||||
*/
|
||||
public class OAuth2RefreshTokenAuthenticationTokenTests {
|
||||
private String issuer = "https://example.com/issuer1";
|
||||
private RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
private OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret());
|
||||
private Set<String> scopes = Collections.singleton("scope1");
|
||||
private Map<String, Object> additionalParameters = Collections.singletonMap("param1", "value1");
|
||||
|
||||
@Test
|
||||
public void constructorWhenIssuerNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken(null, "refresh-token", this.clientPrincipal, this.scopes, this.additionalParameters))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("issuer cannot be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenRefreshTokenNullOrEmptyThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken(null, this.clientPrincipal, this.scopes, this.additionalParameters))
|
||||
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken(this.issuer, null, this.clientPrincipal, this.scopes, this.additionalParameters))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("refreshToken cannot be empty");
|
||||
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken("", this.clientPrincipal, this.scopes, this.additionalParameters))
|
||||
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken(this.issuer, "", this.clientPrincipal, this.scopes, this.additionalParameters))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("refreshToken cannot be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenClientPrincipalNullThenThrowIllegalArgumentException() {
|
||||
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken("refresh-token", null, this.scopes, this.additionalParameters))
|
||||
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken(this.issuer, "refresh-token", null, this.scopes, this.additionalParameters))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("clientPrincipal cannot be null");
|
||||
}
|
||||
@@ -62,8 +70,9 @@ public class OAuth2RefreshTokenAuthenticationTokenTests {
|
||||
@Test
|
||||
public void constructorWhenScopesProvidedThenCreated() {
|
||||
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
|
||||
"refresh-token", this.clientPrincipal, this.scopes, this.additionalParameters);
|
||||
this.issuer, "refresh-token", this.clientPrincipal, this.scopes, this.additionalParameters);
|
||||
assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.REFRESH_TOKEN);
|
||||
assertThat(authentication.getIssuer()).isEqualTo(this.issuer);
|
||||
assertThat(authentication.getRefreshToken()).isEqualTo("refresh-token");
|
||||
assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal);
|
||||
assertThat(authentication.getCredentials().toString()).isEmpty();
|
||||
|
||||
@@ -83,7 +83,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
this.registeredClientRepository = mock(RegisteredClientRepository.class);
|
||||
this.authorizationService = mock(OAuth2AuthorizationService.class);
|
||||
this.jwtEncoder = mock(JwtEncoder.class);
|
||||
this.providerSettings = ProviderSettings.builder().issuer("https://auth-server:9000").build();
|
||||
this.providerSettings = ProviderSettings.builder().build();
|
||||
this.authenticationProvider = new OidcClientRegistrationAuthenticationProvider(
|
||||
this.registeredClientRepository, this.authorizationService, this.jwtEncoder);
|
||||
this.authenticationProvider.setProviderSettings(this.providerSettings);
|
||||
@@ -117,13 +117,14 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenPrincipalNotOAuth2TokenAuthenticationTokenThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
TestingAuthenticationToken principal = new TestingAuthenticationToken("principal", "credentials");
|
||||
OidcClientRegistration clientRegistration = OidcClientRegistration.builder()
|
||||
.redirectUri("https://client.example.com")
|
||||
.build();
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, clientRegistration);
|
||||
issuer, principal, clientRegistration);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -133,13 +134,14 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenPrincipalNotAuthenticatedThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
JwtAuthenticationToken principal = new JwtAuthenticationToken(createJwtClientRegistration());
|
||||
OidcClientRegistration clientRegistration = OidcClientRegistration.builder()
|
||||
.redirectUri("https://client.example.com")
|
||||
.build();
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, clientRegistration);
|
||||
issuer, principal, clientRegistration);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -149,6 +151,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenAccessTokenNotFoundThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwtClientRegistration();
|
||||
JwtAuthenticationToken principal = new JwtAuthenticationToken(
|
||||
jwt, AuthorityUtils.createAuthorityList("SCOPE_client.create"));
|
||||
@@ -157,7 +160,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
.build();
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, clientRegistration);
|
||||
issuer, principal, clientRegistration);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -169,6 +172,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenAccessTokenNotActiveThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwtClientRegistration();
|
||||
OAuth2AccessToken jwtAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
jwt.getTokenValue(), jwt.getIssuedAt(),
|
||||
@@ -188,7 +192,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
.build();
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, clientRegistration);
|
||||
issuer, principal, clientRegistration);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -200,6 +204,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientRegistrationRequestAndAccessTokenNotAuthorizedThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwt(Collections.singleton("unauthorized.scope"));
|
||||
OAuth2AccessToken jwtAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
jwt.getTokenValue(), jwt.getIssuedAt(),
|
||||
@@ -218,7 +223,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
.build();
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, clientRegistration);
|
||||
issuer, principal, clientRegistration);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -230,6 +235,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientRegistrationRequestAndAccessTokenContainsRequiredScopeAndAdditionalScopeThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwt(new HashSet<>(Arrays.asList("client.create", "scope1")));
|
||||
OAuth2AccessToken jwtAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
jwt.getTokenValue(), jwt.getIssuedAt(),
|
||||
@@ -248,7 +254,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
.build();
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, clientRegistration);
|
||||
issuer, principal, clientRegistration);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -260,6 +266,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientRegistrationRequestAndInvalidRedirectUriThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwtClientRegistration();
|
||||
OAuth2AccessToken jwtAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
jwt.getTokenValue(), jwt.getIssuedAt(),
|
||||
@@ -280,7 +287,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
// @formatter:on
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, clientRegistration);
|
||||
issuer, principal, clientRegistration);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -292,6 +299,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientRegistrationRequestAndRedirectUriContainsFragmentThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwtClientRegistration();
|
||||
OAuth2AccessToken jwtAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
jwt.getTokenValue(), jwt.getIssuedAt(),
|
||||
@@ -312,7 +320,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
// @formatter:on
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, clientRegistration);
|
||||
issuer, principal, clientRegistration);
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -324,6 +332,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientRegistrationRequestAndValidAccessTokenThenReturnClientRegistration() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwtClientRegistration();
|
||||
OAuth2AccessToken jwtAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
jwt.getTokenValue(), jwt.getIssuedAt(),
|
||||
@@ -350,7 +359,8 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
// @formatter:on
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, clientRegistration);
|
||||
issuer, principal, clientRegistration);
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authenticationResult =
|
||||
(OidcClientRegistrationAuthenticationToken) this.authenticationProvider.authenticate(authentication);
|
||||
|
||||
@@ -415,7 +425,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
assertThat(clientRegistrationResult.getIdTokenSignedResponseAlgorithm())
|
||||
.isEqualTo(registeredClientResult.getTokenSettings().getIdTokenSignatureAlgorithm().getName());
|
||||
|
||||
String expectedRegistrationClientUrl = UriComponentsBuilder.fromUriString(this.providerSettings.getIssuer())
|
||||
String expectedRegistrationClientUrl = UriComponentsBuilder.fromUriString(issuer)
|
||||
.path(this.providerSettings.getOidcClientRegistrationEndpoint())
|
||||
.queryParam(OAuth2ParameterNames.CLIENT_ID, registeredClientResult.getClientId()).toUriString();
|
||||
|
||||
@@ -425,6 +435,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientConfigurationRequestAndAccessTokenNotAuthorizedThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwt(Collections.singleton("unauthorized.scope"));
|
||||
OAuth2AccessToken jwtAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
jwt.getTokenValue(), jwt.getIssuedAt(),
|
||||
@@ -440,7 +451,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
jwt, AuthorityUtils.createAuthorityList("SCOPE_unauthorized.scope"));
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, registeredClient.getClientId());
|
||||
issuer, principal, registeredClient.getClientId());
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -452,6 +463,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientConfigurationRequestAndAccessTokenContainsRequiredScopeAndAdditionalScopeThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwt(new HashSet<>(Arrays.asList("client.read", "scope1")));
|
||||
OAuth2AccessToken jwtAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
jwt.getTokenValue(), jwt.getIssuedAt(),
|
||||
@@ -467,7 +479,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
jwt, AuthorityUtils.createAuthorityList("SCOPE_client.read", "SCOPE_scope1"));
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, registeredClient.getClientId());
|
||||
issuer, principal, registeredClient.getClientId());
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -479,6 +491,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientConfigurationRequestAndRegisteredClientNotFoundThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwtClientConfiguration();
|
||||
OAuth2AccessToken jwtAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
jwt.getTokenValue(), jwt.getIssuedAt(),
|
||||
@@ -494,7 +507,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
jwt, AuthorityUtils.createAuthorityList("SCOPE_client.read"));
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, registeredClient.getClientId());
|
||||
issuer, principal, registeredClient.getClientId());
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -508,6 +521,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientConfigurationRequestClientIdNotEqualToAuthorizedClientThenThrowOAuth2AuthenticationException() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwtClientConfiguration();
|
||||
OAuth2AccessToken jwtAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
jwt.getTokenValue(), jwt.getIssuedAt(),
|
||||
@@ -527,7 +541,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
jwt, AuthorityUtils.createAuthorityList("SCOPE_client.read"));
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, registeredClient.getClientId());
|
||||
issuer, principal, registeredClient.getClientId());
|
||||
|
||||
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
|
||||
.isInstanceOf(OAuth2AuthenticationException.class)
|
||||
@@ -541,6 +555,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
|
||||
@Test
|
||||
public void authenticateWhenClientConfigurationRequestAndValidAccessTokenThenReturnClientRegistration() {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwtClientConfiguration();
|
||||
OAuth2AccessToken jwtAccessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
|
||||
jwt.getTokenValue(), jwt.getIssuedAt(),
|
||||
@@ -560,7 +575,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
jwt, AuthorityUtils.createAuthorityList("SCOPE_client.read"));
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
principal, registeredClient.getClientId());
|
||||
issuer, principal, registeredClient.getClientId());
|
||||
|
||||
OidcClientRegistrationAuthenticationToken authenticationResult =
|
||||
(OidcClientRegistrationAuthenticationToken) this.authenticationProvider.authenticate(authentication);
|
||||
@@ -597,7 +612,7 @@ public class OidcClientRegistrationAuthenticationProviderTests {
|
||||
assertThat(clientRegistrationResult.getIdTokenSignedResponseAlgorithm())
|
||||
.isEqualTo(registeredClient.getTokenSettings().getIdTokenSignatureAlgorithm().getName());
|
||||
|
||||
String expectedRegistrationClientUrl = UriComponentsBuilder.fromUriString(this.providerSettings.getIssuer())
|
||||
String expectedRegistrationClientUrl = UriComponentsBuilder.fromUriString(issuer)
|
||||
.path(this.providerSettings.getOidcClientRegistrationEndpoint())
|
||||
.queryParam(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()).toUriString();
|
||||
|
||||
|
||||
@@ -29,43 +29,52 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
* @author Joe Grandja
|
||||
*/
|
||||
public class OidcClientRegistrationAuthenticationTokenTests {
|
||||
private String issuer = "https://example.com/issuer1";
|
||||
private TestingAuthenticationToken principal = new TestingAuthenticationToken("principal", "credentials");
|
||||
private OidcClientRegistration clientRegistration = OidcClientRegistration.builder()
|
||||
.redirectUri("https://client.example.com").build();
|
||||
|
||||
@Test
|
||||
public void constructorWhenIssuerNullThenThrowIllegalArgumentException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new OidcClientRegistrationAuthenticationToken(null, this.principal, this.clientRegistration))
|
||||
.withMessage("issuer cannot be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenPrincipalNullThenThrowIllegalArgumentException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new OidcClientRegistrationAuthenticationToken(null, this.clientRegistration))
|
||||
.isThrownBy(() -> new OidcClientRegistrationAuthenticationToken(this.issuer, null, this.clientRegistration))
|
||||
.withMessage("principal cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenClientRegistrationNullThenThrowIllegalArgumentException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new OidcClientRegistrationAuthenticationToken(this.principal, (OidcClientRegistration) null))
|
||||
.isThrownBy(() -> new OidcClientRegistrationAuthenticationToken(this.issuer, this.principal, (OidcClientRegistration) null))
|
||||
.withMessage("clientRegistration cannot be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenClientIdNullThenThrowIllegalArgumentException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new OidcClientRegistrationAuthenticationToken(this.principal, (String) null))
|
||||
.isThrownBy(() -> new OidcClientRegistrationAuthenticationToken(this.issuer, this.principal, (String) null))
|
||||
.withMessage("clientId cannot be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenClientIdEmptyThenThrowIllegalArgumentException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new OidcClientRegistrationAuthenticationToken(this.principal, ""))
|
||||
.isThrownBy(() -> new OidcClientRegistrationAuthenticationToken(this.issuer, this.principal, ""))
|
||||
.withMessage("clientId cannot be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorWhenOidcClientRegistrationProvidedThenCreated() {
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
this.principal, this.clientRegistration);
|
||||
this.issuer, this.principal, this.clientRegistration);
|
||||
|
||||
assertThat(authentication.getIssuer()).isEqualTo(this.issuer);
|
||||
assertThat(authentication.getPrincipal()).isEqualTo(this.principal);
|
||||
assertThat(authentication.getCredentials().toString()).isEmpty();
|
||||
assertThat(authentication.getClientRegistration()).isEqualTo(this.clientRegistration);
|
||||
@@ -76,8 +85,9 @@ public class OidcClientRegistrationAuthenticationTokenTests {
|
||||
@Test
|
||||
public void constructorWhenClientIdProvidedThenCreated() {
|
||||
OidcClientRegistrationAuthenticationToken authentication = new OidcClientRegistrationAuthenticationToken(
|
||||
this.principal, "client-1");
|
||||
this.issuer, this.principal, "client-1");
|
||||
|
||||
assertThat(authentication.getIssuer()).isEqualTo(this.issuer);
|
||||
assertThat(authentication.getPrincipal()).isEqualTo(this.principal);
|
||||
assertThat(authentication.getCredentials().toString()).isEmpty();
|
||||
assertThat(authentication.getClientRegistration()).isNull();
|
||||
|
||||
@@ -53,6 +53,7 @@ import org.springframework.security.oauth2.jwt.JwtClaimsSet;
|
||||
import org.springframework.security.oauth2.jwt.TestJoseHeaders;
|
||||
import org.springframework.security.oauth2.jwt.TestJwtClaimsSets;
|
||||
import org.springframework.security.oauth2.server.authorization.oidc.authentication.OidcClientRegistrationAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.authorization.web.WebAttributes;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -188,6 +189,7 @@ public class OidcClientRegistrationEndpointFilterTests {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri);
|
||||
request.setServletPath(requestUri);
|
||||
writeClientRegistrationRequest(request, clientRegistrationRequest);
|
||||
request.setAttribute(WebAttributes.ISSUER, "https://example.com/issuer1");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain filterChain = mock(FilterChain.class);
|
||||
|
||||
@@ -225,12 +227,13 @@ public class OidcClientRegistrationEndpointFilterTests {
|
||||
.build();
|
||||
// @formatter:on
|
||||
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwt("client.create");
|
||||
JwtAuthenticationToken principal = new JwtAuthenticationToken(
|
||||
jwt, AuthorityUtils.createAuthorityList("SCOPE_client.create"));
|
||||
|
||||
OidcClientRegistrationAuthenticationToken clientRegistrationAuthenticationResult =
|
||||
new OidcClientRegistrationAuthenticationToken(principal, expectedClientRegistrationResponse);
|
||||
new OidcClientRegistrationAuthenticationToken(issuer, principal, expectedClientRegistrationResponse);
|
||||
|
||||
when(this.authenticationManager.authenticate(any())).thenReturn(clientRegistrationAuthenticationResult);
|
||||
|
||||
@@ -242,6 +245,7 @@ public class OidcClientRegistrationEndpointFilterTests {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri);
|
||||
request.setServletPath(requestUri);
|
||||
writeClientRegistrationRequest(request, clientRegistrationRequest);
|
||||
request.setAttribute(WebAttributes.ISSUER, issuer);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain filterChain = mock(FilterChain.class);
|
||||
@@ -370,6 +374,7 @@ public class OidcClientRegistrationEndpointFilterTests {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
|
||||
request.setServletPath(requestUri);
|
||||
request.setParameter(OAuth2ParameterNames.CLIENT_ID, "client1");
|
||||
request.setAttribute(WebAttributes.ISSUER, "https://example.com/issuer1");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain filterChain = mock(FilterChain.class);
|
||||
|
||||
@@ -402,12 +407,13 @@ public class OidcClientRegistrationEndpointFilterTests {
|
||||
.build();
|
||||
// @formatter:on
|
||||
|
||||
String issuer = "https://example.com/issuer1";
|
||||
Jwt jwt = createJwt("client.read");
|
||||
JwtAuthenticationToken principal = new JwtAuthenticationToken(
|
||||
jwt, AuthorityUtils.createAuthorityList("SCOPE_client.read"));
|
||||
|
||||
OidcClientRegistrationAuthenticationToken clientConfigurationAuthenticationResult =
|
||||
new OidcClientRegistrationAuthenticationToken(principal, expectedClientRegistrationResponse);
|
||||
new OidcClientRegistrationAuthenticationToken(issuer, principal, expectedClientRegistrationResponse);
|
||||
|
||||
when(this.authenticationManager.authenticate(any())).thenReturn(clientConfigurationAuthenticationResult);
|
||||
|
||||
@@ -419,6 +425,7 @@ public class OidcClientRegistrationEndpointFilterTests {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
|
||||
request.setServletPath(requestUri);
|
||||
request.setParameter(OAuth2ParameterNames.CLIENT_ID, expectedClientRegistrationResponse.getClientId());
|
||||
request.setAttribute(WebAttributes.ISSUER, issuer);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain filterChain = mock(FilterChain.class);
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.web.WebAttributes;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
@@ -98,6 +99,7 @@ public class OidcProviderConfigurationEndpointFilterTests {
|
||||
String requestUri = DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
|
||||
request.setServletPath(requestUri);
|
||||
request.setAttribute(WebAttributes.ISSUER, providerSettings.getIssuer());
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain filterChain = mock(FilterChain.class);
|
||||
|
||||
@@ -130,6 +132,7 @@ public class OidcProviderConfigurationEndpointFilterTests {
|
||||
String requestUri = DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI;
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
|
||||
request.setServletPath(requestUri);
|
||||
request.setAttribute(WebAttributes.ISSUER, providerSettings.getIssuer());
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain filterChain = mock(FilterChain.class);
|
||||
|
||||
|
||||
@@ -146,4 +146,36 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
|
||||
.withMessage("issuer must be a valid URL");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doFilterWhenProviderSettingsWithIssuerNotSetThenIssuerResolvesFromRequest() throws Exception {
|
||||
ProviderSettings providerSettings = ProviderSettings.builder().build();
|
||||
OAuth2AuthorizationServerMetadataEndpointFilter filter =
|
||||
new OAuth2AuthorizationServerMetadataEndpointFilter(providerSettings);
|
||||
|
||||
String requestUri = DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI;
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
|
||||
request.setServletPath(requestUri);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
FilterChain filterChain = mock(FilterChain.class);
|
||||
|
||||
filter.doFilter(request, response, filterChain);
|
||||
|
||||
verifyNoInteractions(filterChain);
|
||||
|
||||
assertThat(response.getContentType()).isEqualTo(MediaType.APPLICATION_JSON_VALUE);
|
||||
String authorizationServerMetadataResponse = response.getContentAsString();
|
||||
assertThat(authorizationServerMetadataResponse).contains("\"issuer\":\"http://localhost\"");
|
||||
assertThat(authorizationServerMetadataResponse).contains("\"authorization_endpoint\":\"http://localhost/oauth2/authorize\"");
|
||||
assertThat(authorizationServerMetadataResponse).contains("\"token_endpoint\":\"http://localhost/oauth2/token\"");
|
||||
assertThat(authorizationServerMetadataResponse).contains("\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\"]");
|
||||
assertThat(authorizationServerMetadataResponse).contains("\"jwks_uri\":\"http://localhost/oauth2/jwks\"");
|
||||
assertThat(authorizationServerMetadataResponse).contains("\"response_types_supported\":[\"code\"]");
|
||||
assertThat(authorizationServerMetadataResponse).contains("\"grant_types_supported\":[\"authorization_code\",\"client_credentials\",\"refresh_token\"]");
|
||||
assertThat(authorizationServerMetadataResponse).contains("\"revocation_endpoint\":\"http://localhost/oauth2/revoke\"");
|
||||
assertThat(authorizationServerMetadataResponse).contains("\"revocation_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\"]");
|
||||
assertThat(authorizationServerMetadataResponse).contains("\"introspection_endpoint\":\"http://localhost/oauth2/introspect\"");
|
||||
assertThat(authorizationServerMetadataResponse).contains("\"introspection_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\"]");
|
||||
assertThat(authorizationServerMetadataResponse).contains("\"code_challenge_methods_supported\":[\"plain\",\"S256\"]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -489,12 +489,13 @@ public class OAuth2TokenEndpointFilterTests {
|
||||
|
||||
@Test
|
||||
public void doFilterWhenCustomAuthenticationConverterThenUsed() throws Exception {
|
||||
String issuer = "https://example.com/issuer1";
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
|
||||
Authentication clientPrincipal = new OAuth2ClientAuthenticationToken(
|
||||
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
|
||||
|
||||
OAuth2AuthorizationCodeAuthenticationToken authorizationCodeAuthentication =
|
||||
new OAuth2AuthorizationCodeAuthenticationToken("code", clientPrincipal, null, null);
|
||||
new OAuth2AuthorizationCodeAuthenticationToken(issuer, "code", clientPrincipal, null, null);
|
||||
|
||||
AuthenticationConverter authenticationConverter = mock(AuthenticationConverter.class);
|
||||
when(authenticationConverter.convert(any())).thenReturn(authorizationCodeAuthentication);
|
||||
@@ -613,6 +614,8 @@ public class OAuth2TokenEndpointFilterTests {
|
||||
request.addParameter(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId());
|
||||
request.addParameter("custom-param-1", "custom-value-1");
|
||||
|
||||
request.setAttribute(WebAttributes.ISSUER, "https://example.com/issuer1");
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -627,6 +630,8 @@ public class OAuth2TokenEndpointFilterTests {
|
||||
StringUtils.collectionToDelimitedString(registeredClient.getScopes(), " "));
|
||||
request.addParameter("custom-param-1", "custom-value-1");
|
||||
|
||||
request.setAttribute(WebAttributes.ISSUER, "https://example.com/issuer1");
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -642,6 +647,8 @@ public class OAuth2TokenEndpointFilterTests {
|
||||
StringUtils.collectionToDelimitedString(registeredClient.getScopes(), " "));
|
||||
request.addParameter("custom-param-1", "custom-value-1");
|
||||
|
||||
request.setAttribute(WebAttributes.ISSUER, "https://example.com/issuer1");
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ import org.springframework.security.oauth2.server.authorization.client.InMemoryR
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
|
||||
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
@@ -101,11 +100,6 @@ public class AuthorizationServerConfig {
|
||||
return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ProviderSettings providerSettings() {
|
||||
return ProviderSettings.builder().issuer("http://auth-server:9000").build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OAuth2AuthorizationConsentService authorizationConsentService() {
|
||||
// Will be used by the ConsentController
|
||||
|
||||
@@ -45,7 +45,6 @@ import org.springframework.security.oauth2.server.authorization.client.JdbcRegis
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
|
||||
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
|
||||
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
/**
|
||||
@@ -105,11 +104,6 @@ public class AuthorizationServerConfig {
|
||||
return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ProviderSettings providerSettings() {
|
||||
return ProviderSettings.builder().issuer("http://auth-server:9000").build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EmbeddedDatabase embeddedDatabase() {
|
||||
// @formatter:off
|
||||
|
||||
Reference in New Issue
Block a user