Propagate additional token request parameters

Closes gh-226
This commit is contained in:
Joe Grandja
2021-02-11 09:50:04 -05:00
parent b5d47366ad
commit 7652d0ebbe
9 changed files with 115 additions and 94 deletions

View File

@@ -108,7 +108,8 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
TestingAuthenticationToken clientPrincipal = new TestingAuthenticationToken(
registeredClient.getClientId(), registeredClient.getClientSecret());
OAuth2ClientCredentialsAuthenticationToken authentication = new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal);
OAuth2ClientCredentialsAuthenticationToken authentication =
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
@@ -122,7 +123,8 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId(), registeredClient.getClientSecret(), ClientAuthenticationMethod.BASIC, null);
OAuth2ClientCredentialsAuthenticationToken authentication = new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal);
OAuth2ClientCredentialsAuthenticationToken authentication =
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
@@ -137,7 +139,8 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
.authorizationGrantTypes(grantTypes -> grantTypes.remove(AuthorizationGrantType.CLIENT_CREDENTIALS))
.build();
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
OAuth2ClientCredentialsAuthenticationToken authentication = new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal);
OAuth2ClientCredentialsAuthenticationToken authentication =
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
@@ -151,7 +154,7 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
OAuth2ClientCredentialsAuthenticationToken authentication = new OAuth2ClientCredentialsAuthenticationToken(
clientPrincipal, Collections.singleton("invalid-scope"));
clientPrincipal, Collections.singleton("invalid-scope"), null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
@@ -166,7 +169,7 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
Set<String> requestedScope = Collections.singleton("scope1");
OAuth2ClientCredentialsAuthenticationToken authentication =
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, requestedScope);
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, requestedScope, null);
when(this.jwtEncoder.encode(any(), any()))
.thenReturn(createJwt(Collections.singleton("mapped-scoped")));
@@ -180,7 +183,8 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
public void authenticateWhenValidAuthenticationThenReturnAccessToken() {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
OAuth2ClientCredentialsAuthenticationToken authentication = new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal);
OAuth2ClientCredentialsAuthenticationToken authentication =
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
when(this.jwtEncoder.encode(any(), any())).thenReturn(createJwt(registeredClient.getScopes()));

View File

@@ -16,6 +16,7 @@
package org.springframework.security.oauth2.server.authorization.authentication;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
@@ -34,42 +35,39 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class OAuth2ClientCredentialsAuthenticationTokenTests {
private final OAuth2ClientAuthenticationToken clientPrincipal =
new OAuth2ClientAuthenticationToken(TestRegisteredClients.registeredClient().build());
private Set<String> scopes = Collections.singleton("scope1");
private Map<String, Object> additionalParameters = Collections.singletonMap("param1", "value1");
@Test
public void constructorWhenClientPrincipalNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new OAuth2ClientCredentialsAuthenticationToken(null))
assertThatThrownBy(() -> new OAuth2ClientCredentialsAuthenticationToken(null, this.scopes, this.additionalParameters))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("clientPrincipal cannot be null");
}
@Test
public void constructorWhenScopesNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new OAuth2ClientCredentialsAuthenticationToken(this.clientPrincipal, null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("scopes cannot be null");
}
@Test
public void constructorWhenClientPrincipalProvidedThenCreated() {
OAuth2ClientCredentialsAuthenticationToken authentication =
new OAuth2ClientCredentialsAuthenticationToken(this.clientPrincipal);
OAuth2ClientCredentialsAuthenticationToken authentication = new OAuth2ClientCredentialsAuthenticationToken(
this.clientPrincipal, this.scopes, this.additionalParameters);
assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.CLIENT_CREDENTIALS);
assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal);
assertThat(authentication.getCredentials().toString()).isEmpty();
assertThat(authentication.getScopes()).isEmpty();
assertThat(authentication.getScopes()).isEqualTo(this.scopes);
assertThat(authentication.getAdditionalParameters()).isEqualTo(this.additionalParameters);
}
@Test
public void constructorWhenScopesProvidedThenCreated() {
Set<String> expectedScopes = Collections.singleton("test-scope");
OAuth2ClientCredentialsAuthenticationToken authentication =
new OAuth2ClientCredentialsAuthenticationToken(this.clientPrincipal, expectedScopes);
OAuth2ClientCredentialsAuthenticationToken authentication = new OAuth2ClientCredentialsAuthenticationToken(
this.clientPrincipal, expectedScopes, this.additionalParameters);
assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.CLIENT_CREDENTIALS);
assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal);
assertThat(authentication.getCredentials().toString()).isEmpty();
assertThat(authentication.getScopes()).isEqualTo(expectedScopes);
assertThat(authentication.getAdditionalParameters()).isEqualTo(this.additionalParameters);
}
}

View File

@@ -124,7 +124,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal);
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
@@ -169,7 +169,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal);
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
@@ -199,7 +199,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
Set<String> requestedScopes = new HashSet<>(authorizedScopes);
requestedScopes.remove("scope1");
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, requestedScopes);
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, requestedScopes, null);
OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
(OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication);
@@ -221,7 +221,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
Set<String> requestedScopes = new HashSet<>(authorizedScopes);
requestedScopes.add("unauthorized");
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, requestedScopes);
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, requestedScopes, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
@@ -235,7 +235,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
"invalid", clientPrincipal);
"invalid", clientPrincipal, null, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
@@ -250,7 +250,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
TestingAuthenticationToken clientPrincipal = new TestingAuthenticationToken(
registeredClient.getClientId(), registeredClient.getClientSecret());
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
"refresh-token", clientPrincipal);
"refresh-token", clientPrincipal, null, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
@@ -265,7 +265,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
registeredClient.getClientId(), registeredClient.getClientSecret(), ClientAuthenticationMethod.BASIC, null);
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
"refresh-token", clientPrincipal);
"refresh-token", clientPrincipal, null, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
@@ -286,7 +286,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
TestRegisteredClients.registeredClient2().build());
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal);
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
@@ -308,7 +308,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal);
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
@@ -331,7 +331,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal);
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)
@@ -355,7 +355,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal);
authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null);
assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.isInstanceOf(OAuth2AuthenticationException.class)

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.security.oauth2.server.authorization.authentication;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
@@ -34,42 +34,37 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
* @since 0.0.3
*/
public class OAuth2RefreshTokenAuthenticationTokenTests {
private final OAuth2ClientAuthenticationToken clientPrincipal =
private OAuth2ClientAuthenticationToken clientPrincipal =
new OAuth2ClientAuthenticationToken(TestRegisteredClients.registeredClient().build());
private Set<String> scopes = Collections.singleton("scope1");
private Map<String, Object> additionalParameters = Collections.singletonMap("param1", "value1");
@Test
public void constructorWhenRefreshTokenNullOrEmptyThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken(null, this.clientPrincipal))
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken(null, this.clientPrincipal, this.scopes, this.additionalParameters))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("refreshToken cannot be empty");
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken("", this.clientPrincipal))
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken("", this.clientPrincipal, this.scopes, this.additionalParameters))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("refreshToken cannot be empty");
}
@Test
public void constructorWhenClientPrincipalNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken("refresh-token", null))
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken("refresh-token", null, this.scopes, this.additionalParameters))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("clientPrincipal cannot be null");
}
@Test
public void constructorWhenScopesNullThenThrowIllegalArgumentException() {
assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken("refresh-token", this.clientPrincipal, null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("scopes cannot be null");
}
@Test
public void constructorWhenScopesProvidedThenCreated() {
Set<String> expectedScopes = new HashSet<>(Arrays.asList("scope-a", "scope-b"));
OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
"refresh-token", this.clientPrincipal, expectedScopes);
"refresh-token", this.clientPrincipal, this.scopes, this.additionalParameters);
assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.REFRESH_TOKEN);
assertThat(authentication.getRefreshToken()).isEqualTo("refresh-token");
assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal);
assertThat(authentication.getCredentials().toString()).isEmpty();
assertThat(authentication.getScopes()).isEqualTo(expectedScopes);
assertThat(authentication.getScopes()).isEqualTo(this.scopes);
assertThat(authentication.getAdditionalParameters()).isEqualTo(this.additionalParameters);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020 the original author or authors.
* 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.
@@ -15,10 +15,22 @@
*/
package org.springframework.security.oauth2.server.authorization.web;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.mock.http.client.MockClientHttpResponse;
@@ -47,16 +59,6 @@ import org.springframework.security.oauth2.server.authorization.client.Registere
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
import org.springframework.util.StringUtils;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.entry;
@@ -232,6 +234,8 @@ public class OAuth2TokenEndpointFilterTests {
assertThat(authorizationCodeAuthentication.getPrincipal()).isEqualTo(clientPrincipal);
assertThat(authorizationCodeAuthentication.getRedirectUri()).isEqualTo(
request.getParameter(OAuth2ParameterNames.REDIRECT_URI));
assertThat(authorizationCodeAuthentication.getAdditionalParameters())
.containsExactly(entry("custom-param-1", "custom-value-1"));
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response);
@@ -292,6 +296,8 @@ public class OAuth2TokenEndpointFilterTests {
clientCredentialsAuthenticationCaptor.getValue();
assertThat(clientCredentialsAuthentication.getPrincipal()).isEqualTo(clientPrincipal);
assertThat(clientCredentialsAuthentication.getScopes()).isEqualTo(registeredClient.getScopes());
assertThat(clientCredentialsAuthentication.getAdditionalParameters())
.containsExactly(entry("custom-param-1", "custom-value-1"));
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response);
@@ -372,6 +378,8 @@ public class OAuth2TokenEndpointFilterTests {
assertThat(refreshTokenAuthenticationToken.getRefreshToken()).isEqualTo(refreshToken.getTokenValue());
assertThat(refreshTokenAuthenticationToken.getPrincipal()).isEqualTo(clientPrincipal);
assertThat(refreshTokenAuthenticationToken.getScopes()).isEqualTo(registeredClient.getScopes());
assertThat(refreshTokenAuthenticationToken.getAdditionalParameters())
.containsExactly(entry("custom-param-1", "custom-value-1"));
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response);
@@ -429,6 +437,7 @@ public class OAuth2TokenEndpointFilterTests {
request.addParameter(OAuth2ParameterNames.REDIRECT_URI, redirectUris[0]);
// The client does not need to send the client ID param, but we are resilient in case they do
request.addParameter(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId());
request.addParameter("custom-param-1", "custom-value-1");
return request;
}
@@ -441,6 +450,7 @@ public class OAuth2TokenEndpointFilterTests {
request.addParameter(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue());
request.addParameter(OAuth2ParameterNames.SCOPE,
StringUtils.collectionToDelimitedString(registeredClient.getScopes(), " "));
request.addParameter("custom-param-1", "custom-value-1");
return request;
}
@@ -454,6 +464,7 @@ public class OAuth2TokenEndpointFilterTests {
request.addParameter(OAuth2ParameterNames.REFRESH_TOKEN, "refresh-token");
request.addParameter(OAuth2ParameterNames.SCOPE,
StringUtils.collectionToDelimitedString(registeredClient.getScopes(), " "));
request.addParameter("custom-param-1", "custom-value-1");
return request;
}