Remove deprecated TokenExchangeRequest.additionalParameters()

Closes #37925

Signed-off-by: Giuseppe Graziano <g.graziano94@gmail.com>
This commit is contained in:
Giuseppe Graziano 2025-03-14 12:19:33 +01:00 committed by Marek Posolda
parent be4db3ada0
commit 5a0c68e624
4 changed files with 56 additions and 70 deletions

View File

@ -12,8 +12,9 @@ public class TokenExchangeRequest extends AbstractHttpPostRequest<TokenExchangeR
private final String subjectToken;
private final String subjectTokenType;
private String requestedTokenType;
private String requestedSubject;
private List<String> audience;
private Map<String, String> additionalParams;
TokenExchangeRequest(String subjectToken, String subjectTokenType, AbstractOAuthClient<?> client) {
super(client);
@ -26,6 +27,16 @@ public class TokenExchangeRequest extends AbstractHttpPostRequest<TokenExchangeR
return client.getEndpoints().getToken();
}
public TokenExchangeRequest requestedTokenType(String requestedTokenType) {
this.requestedTokenType = requestedTokenType;
return this;
}
public TokenExchangeRequest requestedSubject(String requestedSubject) {
this.requestedSubject = requestedSubject;
return this;
}
public TokenExchangeRequest audience(List<String> audience) {
this.audience = audience;
return this;
@ -36,28 +47,22 @@ public class TokenExchangeRequest extends AbstractHttpPostRequest<TokenExchangeR
return this;
}
/**
* @deprecated Additional parameters should not be passed as a map, instead specific methods should be added
* for example <code>requestedTokenType(tokenType)</code>
*/
@Deprecated
public TokenExchangeRequest additionalParams(Map<String, String> additionalParams) {
this.additionalParams = additionalParams;
return this;
}
protected void initRequest() {
parameter(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE);
parameter(OAuth2Constants.SUBJECT_TOKEN, subjectToken);
parameter(OAuth2Constants.SUBJECT_TOKEN_TYPE, subjectTokenType != null ? subjectTokenType : OAuth2Constants.ACCESS_TOKEN_TYPE);
if (audience != null) {
audience.forEach(a -> parameter(OAuth2Constants.AUDIENCE, a));
if (requestedTokenType != null) {
parameter(OAuth2Constants.REQUESTED_TOKEN_TYPE, requestedTokenType);
}
if (additionalParams != null) {
additionalParams.forEach(this::parameter);
if (requestedSubject != null) {
parameter(OAuth2Constants.REQUESTED_SUBJECT, requestedSubject);
}
if (audience != null) {
audience.forEach(a -> parameter(OAuth2Constants.AUDIENCE, a));
}
parameter(OAuth2Constants.SCOPE, client.config().getScope(false));

View File

@ -246,11 +246,8 @@ public class ClientTokenExchangeSAML2Test extends AbstractKeycloakTest {
Assert.assertEquals(token.getPreferredUsername(), "user");
Assert.assertTrue(token.getRealmAccess() == null || !token.getRealmAccess().isUserInRole("example"));
Map<String, String> params = new HashMap<>();
params.put(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.SAML2_TOKEN_TYPE);
{
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_SIGNED_TARGET).additionalParams(params).send();
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_SIGNED_TARGET).requestedTokenType(OAuth2Constants.SAML2_TOKEN_TYPE).send();
String exchangedTokenString = response.getAccessToken();
String assertionXML = new String(Base64Url.decode(exchangedTokenString), StandardCharsets.UTF_8);
@ -281,7 +278,7 @@ public class ClientTokenExchangeSAML2Test extends AbstractKeycloakTest {
{
oauth.client("legal", "secret");
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_SIGNED_TARGET).additionalParams(params).send();
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_SIGNED_TARGET).requestedTokenType(OAuth2Constants.SAML2_TOKEN_TYPE).send();
String exchangedTokenString = response.getAccessToken();
String assertionXML = new String(Base64Url.decode(exchangedTokenString), StandardCharsets.UTF_8);
@ -308,7 +305,7 @@ public class ClientTokenExchangeSAML2Test extends AbstractKeycloakTest {
}
{
oauth.client("illegal", "secret");
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_SIGNED_TARGET).additionalParams(params).send();
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_SIGNED_TARGET).requestedTokenType(OAuth2Constants.SAML2_TOKEN_TYPE).send();
Assert.assertEquals(403, response.getStatusCode());
}
}
@ -327,11 +324,8 @@ public class ClientTokenExchangeSAML2Test extends AbstractKeycloakTest {
Assert.assertEquals(token.getPreferredUsername(), "user");
Assert.assertTrue(token.getRealmAccess() == null || !token.getRealmAccess().isUserInRole("example"));
Map<String, String> params = new HashMap<>();
params.put(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.SAML2_TOKEN_TYPE);
{
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_ENCRYPTED_TARGET).additionalParams(params).send();
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_ENCRYPTED_TARGET).requestedTokenType(OAuth2Constants.SAML2_TOKEN_TYPE).send();
String exchangedTokenString = response.getAccessToken();
String assertionXML = new String(Base64Url.decode(exchangedTokenString), StandardCharsets.UTF_8);
@ -375,11 +369,8 @@ public class ClientTokenExchangeSAML2Test extends AbstractKeycloakTest {
Assert.assertEquals(token.getPreferredUsername(), "user");
Assert.assertTrue(token.getRealmAccess() == null || !token.getRealmAccess().isUserInRole("example"));
Map<String, String> params = new HashMap<>();
params.put(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.SAML2_TOKEN_TYPE);
{
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_SIGNED_AND_ENCRYPTED_TARGET).additionalParams(params).send();
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_SIGNED_AND_ENCRYPTED_TARGET).requestedTokenType(OAuth2Constants.SAML2_TOKEN_TYPE).send();
String exchangedTokenString = response.getAccessToken();
String assertionXML = new String(Base64Url.decode(exchangedTokenString), StandardCharsets.UTF_8);
@ -421,11 +412,8 @@ public class ClientTokenExchangeSAML2Test extends AbstractKeycloakTest {
Assert.assertEquals(token.getPreferredUsername(), "user");
Assert.assertTrue(token.getRealmAccess() == null || !token.getRealmAccess().isUserInRole("example"));
Map<String, String> params = new HashMap<>();
params.put(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.SAML2_TOKEN_TYPE);
{
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_UNSIGNED_AND_UNENCRYPTED_TARGET).additionalParams(params).send();
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_UNSIGNED_AND_UNENCRYPTED_TARGET).requestedTokenType(OAuth2Constants.SAML2_TOKEN_TYPE).send();
String exchangedTokenString = response.getAccessToken();
String assertionXML = new String(Base64Url.decode(exchangedTokenString), StandardCharsets.UTF_8);
@ -466,13 +454,10 @@ public class ClientTokenExchangeSAML2Test extends AbstractKeycloakTest {
Assert.assertEquals(token.getPreferredUsername(), "user");
Assert.assertTrue(token.getRealmAccess() == null || !token.getRealmAccess().isUserInRole("example"));
Map<String, String> params = new HashMap<>();
params.put(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.SAML2_TOKEN_TYPE);
// client-exchanger can impersonate from token "user" to user "impersonated-user" and to "target" client
{
params.put(OAuth2Constants.REQUESTED_SUBJECT, "impersonated-user");
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_SIGNED_TARGET).additionalParams(params).send();
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_SIGNED_TARGET).requestedTokenType(OAuth2Constants.SAML2_TOKEN_TYPE).requestedSubject("impersonated-user").send();
String exchangedTokenString = response.getAccessToken();
String assertionXML = new String(Base64Url.decode(exchangedTokenString), StandardCharsets.UTF_8);
@ -514,13 +499,9 @@ public class ClientTokenExchangeSAML2Test extends AbstractKeycloakTest {
Assert.assertEquals(token.getPreferredUsername(), "bad-impersonator");
Assert.assertTrue(token.getRealmAccess() == null || !token.getRealmAccess().isUserInRole("example"));
Map<String, String> params = new HashMap<>();
params.put(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.SAML2_TOKEN_TYPE);
// test that user does not have impersonator permission
{
params.put(OAuth2Constants.REQUESTED_SUBJECT, "impersonated-user");
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_SIGNED_TARGET).additionalParams(params).send();
response = oauth.tokenExchangeRequest(accessToken).audience(SAML_SIGNED_TARGET).requestedTokenType(OAuth2Constants.SAML2_TOKEN_TYPE).requestedSubject("impersonated-user").send();
Assert.assertEquals(403, response.getStatusCode());
}
}

View File

@ -151,7 +151,7 @@ public class StandardTokenExchangeV1Test extends AbstractKeycloakTest {
{
oauth.client("client-exchanger", "secret");
AccessTokenResponse response = oauth.tokenExchangeRequest(accessToken).audience("target").additionalParams(Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE)).send();
AccessTokenResponse response = oauth.tokenExchangeRequest(accessToken).audience("target").requestedTokenType(OAuth2Constants.ACCESS_TOKEN_TYPE).send();
Assert.assertEquals(OAuth2Constants.ACCESS_TOKEN_TYPE, response.getIssuedTokenType());
String exchangedTokenString = response.getAccessToken();
TokenVerifier<AccessToken> verifier = TokenVerifier.create(exchangedTokenString, AccessToken.class);

View File

@ -163,8 +163,8 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
return response.getAccessToken();
}
protected AccessTokenResponse tokenExchange(String subjectToken, String clientId, String secret, List<String> audience, Map<String, String> additionalParams) {
return oauth.tokenExchangeRequest(subjectToken).client(clientId, secret).audience(audience).additionalParams(additionalParams).send();
protected AccessTokenResponse tokenExchange(String subjectToken, String clientId, String secret, List<String> audience, String requestedTokenType) {
return oauth.tokenExchangeRequest(subjectToken).client(clientId, secret).audience(audience).requestedTokenType(requestedTokenType).send();
}
@Test
@ -210,7 +210,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
oauth.realm(TEST);
String accessToken = resourceOwnerLogin(john.getUsername(), "password", "subject-client", "secret").getAccessToken();
AccessTokenResponse response = tokenExchange(accessToken, "requester-client", "secret", null, Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE));
AccessTokenResponse response = tokenExchange(accessToken, "requester-client", "secret", null, OAuth2Constants.ACCESS_TOKEN_TYPE);
assertAudiencesAndScopes(response, john, List.of("target-client1"), List.of("default-scope1"));
assertNotNull(response.getAccessToken());
assertEquals(TokenUtil.TOKEN_TYPE_BEARER, response.getTokenType());
@ -219,7 +219,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
try (ClientAttributeUpdater clientUpdater = ClientAttributeUpdater.forClient(adminClient, TEST, "requester-client")
.setAttribute(OIDCConfigAttributes.STANDARD_TOKEN_EXCHANGE_REFRESH_ENABLED, Boolean.FALSE.toString())
.update()) {
response = tokenExchange(accessToken, "requester-client", "secret", null, Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
response = tokenExchange(accessToken, "requester-client", "secret", null, OAuth2Constants.REFRESH_TOKEN_TYPE);
assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusCode());
assertEquals(OAuthErrorException.INVALID_REQUEST, response.getError());
assertEquals("requested_token_type unsupported", response.getErrorDescription());
@ -237,14 +237,14 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
try (ClientAttributeUpdater clientUpdater = ClientAttributeUpdater.forClient(adminClient, TEST, "requester-client")
.setAttribute(OIDCConfigAttributes.STANDARD_TOKEN_EXCHANGE_REFRESH_ENABLED, OIDCAdvancedConfigWrapper.TokenExchangeRefreshTokenEnabled.SAME_SESSION.name())
.update()) {
response = tokenExchange(accessToken, "requester-client", "secret", null, Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
response = tokenExchange(accessToken, "requester-client", "secret", null, OAuth2Constants.REFRESH_TOKEN_TYPE);
assertAudiencesAndScopes(response, john, List.of("target-client1"), List.of("default-scope1"), OAuth2Constants.REFRESH_TOKEN_TYPE, "subject-client");
assertNotNull(response.getAccessToken());
assertEquals(TokenUtil.TOKEN_TYPE_BEARER, response.getTokenType());
assertEquals(OAuth2Constants.REFRESH_TOKEN_TYPE, response.getIssuedTokenType());
}
response = tokenExchange(accessToken, "requester-client", "secret", null, Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.ID_TOKEN_TYPE));
response = tokenExchange(accessToken, "requester-client", "secret", null, OAuth2Constants.ID_TOKEN_TYPE);
assertEquals(Response.Status.OK.getStatusCode(), response.getStatusCode());
assertNotNull(response.getAccessToken());
assertEquals(TokenUtil.TOKEN_TYPE_NA, response.getTokenType());
@ -257,7 +257,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
.detail(Details.SUBJECT_TOKEN_CLIENT_ID, "subject-client")
.assertEvent();
response = tokenExchange(accessToken, "requester-client", "secret", null, Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE));
response = tokenExchange(accessToken, "requester-client", "secret", null, OAuth2Constants.JWT_TOKEN_TYPE);
assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusCode());
assertEquals(OAuthErrorException.INVALID_REQUEST, response.getError());
assertEquals("requested_token_type unsupported", response.getErrorDescription());
@ -271,7 +271,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
.detail(Details.SUBJECT_TOKEN_CLIENT_ID, "subject-client")
.assertEvent();
response = tokenExchange(accessToken, "requester-client", "secret", null, Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.SAML2_TOKEN_TYPE));
response = tokenExchange(accessToken, "requester-client", "secret", null, OAuth2Constants.SAML2_TOKEN_TYPE);
assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusCode());
assertEquals(OAuthErrorException.INVALID_REQUEST, response.getError());
assertEquals("requested_token_type unsupported", response.getErrorDescription());
@ -285,7 +285,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
.detail(Details.SUBJECT_TOKEN_CLIENT_ID, "subject-client")
.assertEvent();
response = tokenExchange(accessToken, "requester-client", "secret", null, Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, "WRONG_TOKEN_TYPE"));
response = tokenExchange(accessToken, "requester-client", "secret", null, "WRONG_TOKEN_TYPE");
assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusCode());
assertEquals(OAuthErrorException.INVALID_REQUEST, response.getError());
assertEquals("requested_token_type unsupported", response.getErrorDescription());
@ -448,7 +448,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
public void testExchangeRequestAccessTokenType() throws Exception {
oauth.realm(TEST);
String accessToken = resourceOwnerLogin("john", "password","subject-client", "secret").getAccessToken();
AccessTokenResponse response = tokenExchange(accessToken, "requester-client", "secret", null, Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE));
AccessTokenResponse response = tokenExchange(accessToken, "requester-client", "secret", null, OAuth2Constants.ACCESS_TOKEN_TYPE);
assertEquals(OAuth2Constants.ACCESS_TOKEN_TYPE, response.getIssuedTokenType());
String exchangedTokenString = response.getAccessToken();
TokenVerifier<AccessToken> verifier = TokenVerifier.create(exchangedTokenString, AccessToken.class);
@ -465,7 +465,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
// Exchange request with "scope=oidc" . ID Token should be issued in addition to access-token
oauth.openid(true);
oauth.scope(OAuth2Constants.SCOPE_OPENID);
AccessTokenResponse response = tokenExchange(accessToken, "requester-client", "secret", null, Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE));
AccessTokenResponse response = tokenExchange(accessToken, "requester-client", "secret", null, OAuth2Constants.ACCESS_TOKEN_TYPE);
assertEquals(OAuth2Constants.ACCESS_TOKEN_TYPE, response.getIssuedTokenType());
AccessToken exchangedToken = TokenVerifier.create(response.getAccessToken(), AccessToken.class)
.parse().getToken();
@ -481,13 +481,13 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
// Exchange request without "scope=oidc" . Only access-token should be issued, but not ID Token
oauth.openid(false);
oauth.scope(null);
response = tokenExchange(accessToken, "requester-client", "secret", null, Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE));
response = tokenExchange(accessToken, "requester-client", "secret", null, OAuth2Constants.ACCESS_TOKEN_TYPE);
assertEquals(OAuth2Constants.ACCESS_TOKEN_TYPE, response.getIssuedTokenType());
assertNotNull(response.getAccessToken());
assertNull("ID Token was present, but should not be present", response.getIdToken());
// Exchange request requesting id-token. ID Token should be issued inside "access_token" parameter (as per token-exchange specification https://datatracker.ietf.org/doc/html/rfc8693#name-successful-response - parameter "access_token")
response = tokenExchange(accessToken, "requester-client", "secret", null, Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.ID_TOKEN_TYPE));
response = tokenExchange(accessToken, "requester-client", "secret", null, OAuth2Constants.ID_TOKEN_TYPE);
assertEquals(OAuth2Constants.ID_TOKEN_TYPE, response.getIssuedTokenType());
assertEquals(TokenUtil.TOKEN_TYPE_NA, response.getTokenType());
assertNotNull(response.getAccessToken());
@ -533,7 +533,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
.setAttribute(OIDCConfigAttributes.STANDARD_TOKEN_EXCHANGE_REFRESH_ENABLED, OIDCAdvancedConfigWrapper.TokenExchangeRefreshTokenEnabled.SAME_SESSION.name())
.update()) {
response = tokenExchange(accessToken, "requester-client", "secret", null,
Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
OAuth2Constants.REFRESH_TOKEN_TYPE);
assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusCode());
assertEquals(response.getError(), Errors.INVALID_REQUEST);
assertEquals(response.getErrorDescription(), "Refresh token not valid as requested_token_type because creating a new session is needed");
@ -566,7 +566,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
.setAttribute(OIDCConfigAttributes.STANDARD_TOKEN_EXCHANGE_REFRESH_ENABLED, OIDCAdvancedConfigWrapper.TokenExchangeRefreshTokenEnabled.SAME_SESSION.name())
.update()) {
AccessTokenResponse response = tokenExchange(accessToken, "requester-client", "secret", null,
Map.of(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
OAuth2Constants.REFRESH_TOKEN_TYPE);
assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusCode());
assertEquals(OAuthErrorException.INVALID_REQUEST, response.getError());
assertEquals("requested_token_type unsupported", response.getErrorDescription());
@ -714,7 +714,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
.update()) {
String accessToken = resourceOwnerLogin("mike", "password", "subject-client", "secret").getAccessToken();
oauth.scope("optional-scope2");
AccessTokenResponse response = tokenExchange(accessToken, "requester-client", "secret", List.of("target-client1"), Collections.singletonMap(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
AccessTokenResponse response = tokenExchange(accessToken, "requester-client", "secret", List.of("target-client1"), OAuth2Constants.REFRESH_TOKEN_TYPE);
assertAudiencesAndScopes(response, mike, List.of("target-client1"), List.of("default-scope1", "optional-scope2"), OAuth2Constants.REFRESH_TOKEN_TYPE, "subject-client");
assertNotNull(response.getRefreshToken());
@ -826,7 +826,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
Assert.assertEquals(testingClient.testing(TEST).getClientSessionsCountInUserSession(TEST, sessionId), Integer.valueOf(1));
oauth.scope("offline_access");
AccessTokenResponse response = tokenExchange(accessToken, "requester-client", "secret", List.of("target-client1"), Collections.singletonMap(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
AccessTokenResponse response = tokenExchange(accessToken, "requester-client", "secret", List.of("target-client1"), OAuth2Constants.REFRESH_TOKEN_TYPE);
assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusCode());
assertEquals(OAuthErrorException.INVALID_REQUEST, response.getError());
assertEquals("Scope offline_access not allowed for token exchange", response.getErrorDescription());
@ -863,7 +863,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
// Refresh token-exchange without "scope=offline_access". Not allowed cos a new new "online" user session is needed (as previous one was offline)
oauth.scope(null);
response = tokenExchange(accessToken, "requester-client", "secret", List.of("target-client1"), Collections.singletonMap(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
response = tokenExchange(accessToken, "requester-client", "secret", List.of("target-client1"), OAuth2Constants.REFRESH_TOKEN_TYPE);
assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusCode());
assertEquals(response.getError(), Errors.INVALID_REQUEST);
assertEquals(response.getErrorDescription(), "Refresh token not valid as requested_token_type because creating a new session is needed");
@ -901,7 +901,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
// Token exchange with scope=offline-access should not be allowed
oauth.scope("offline_access");
AccessTokenResponse response = tokenExchange(accessToken, "requester-client", "secret", List.of("target-client1"), Collections.singletonMap(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
AccessTokenResponse response = tokenExchange(accessToken, "requester-client", "secret", List.of("target-client1"), OAuth2Constants.REFRESH_TOKEN_TYPE);
assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatusCode());
// Make sure not new user sessions persisted
@ -960,7 +960,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
AccessTokenResponse accessTokenResponse = resourceOwnerLogin("john", "password", "subject-client", "secret");
//revoke the exchanged access token
AccessTokenResponse tokenExchangeResponse = tokenExchange(accessTokenResponse.getAccessToken(), "requester-client", "secret", null, Collections.singletonMap(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
AccessTokenResponse tokenExchangeResponse = tokenExchange(accessTokenResponse.getAccessToken(), "requester-client", "secret", null, OAuth2Constants.REFRESH_TOKEN_TYPE);
oauth.client("requester-client", "secret");
events.clear();
oauth.doTokenRevoke(tokenExchangeResponse.getAccessToken());
@ -972,7 +972,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
isAccessTokenDisabled(tokenExchangeResponse.getAccessToken(), "requester-client", "secret");
//revoke the exchanged refresh token
tokenExchangeResponse = tokenExchange(accessTokenResponse.getAccessToken(), "requester-client", "secret", null, Collections.singletonMap(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
tokenExchangeResponse = tokenExchange(accessTokenResponse.getAccessToken(), "requester-client", "secret", null, OAuth2Constants.REFRESH_TOKEN_TYPE);
events.clear();
oauth.doTokenRevoke(tokenExchangeResponse.getRefreshToken());
events.expect(EventType.REVOKE_GRANT)
@ -983,7 +983,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
isTokenDisabled(tokenExchangeResponse, "requester-client", "secret");
//revoke the subject access token
tokenExchangeResponse = tokenExchange(accessTokenResponse.getAccessToken(), "requester-client", "secret", null, Collections.singletonMap(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
tokenExchangeResponse = tokenExchange(accessTokenResponse.getAccessToken(), "requester-client", "secret", null, OAuth2Constants.REFRESH_TOKEN_TYPE);
oauth.client("subject-client", "secret");
events.clear();
oauth.doTokenRevoke(accessTokenResponse.getAccessToken());
@ -997,7 +997,7 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
//revoke the subject refresh token
accessTokenResponse = resourceOwnerLogin("john", "password", "subject-client", "secret");
tokenExchangeResponse = tokenExchange(accessTokenResponse.getAccessToken(), "requester-client", "secret", null, Collections.singletonMap(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
tokenExchangeResponse = tokenExchange(accessTokenResponse.getAccessToken(), "requester-client", "secret", null, OAuth2Constants.REFRESH_TOKEN_TYPE);
assertEquals(Response.Status.OK.getStatusCode(), tokenExchangeResponse.getStatusCode());
oauth.client("subject-client", "secret");
events.clear();
@ -1016,9 +1016,9 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
AccessTokenResponse accessTokenResponse2 = oauth.doRefreshTokenRequest(accessTokenResponse1.getRefreshToken());
AccessTokenResponse accessTokenResponse3 = oauth.doRefreshTokenRequest(accessTokenResponse1.getRefreshToken());
AccessTokenResponse tokenExchangeResponse1 = tokenExchange(accessTokenResponse1.getAccessToken(), "requester-client", "secret", null, Collections.singletonMap(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
AccessTokenResponse tokenExchangeResponse1 = tokenExchange(accessTokenResponse1.getAccessToken(), "requester-client", "secret", null, OAuth2Constants.REFRESH_TOKEN_TYPE);
assertEquals(Response.Status.OK.getStatusCode(), tokenExchangeResponse1.getStatusCode());
AccessTokenResponse tokenExchangeResponse2 = tokenExchange(accessTokenResponse2.getAccessToken(), "requester-client", "secret", null, Collections.singletonMap(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
AccessTokenResponse tokenExchangeResponse2 = tokenExchange(accessTokenResponse2.getAccessToken(), "requester-client", "secret", null, OAuth2Constants.REFRESH_TOKEN_TYPE);
assertEquals(Response.Status.OK.getStatusCode(), tokenExchangeResponse2.getStatusCode());
oauth.client("subject-client", "secret");
@ -1047,10 +1047,10 @@ public class StandardTokenExchangeV2Test extends AbstractClientPoliciesTest {
.update();
) {
accessTokenResponse = resourceOwnerLogin("john", "password", "subject-client", "secret");
tokenExchangeResponse1 = tokenExchange(accessTokenResponse.getAccessToken(), "requester-client", "secret", null, Collections.singletonMap(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
tokenExchangeResponse1 = tokenExchange(accessTokenResponse.getAccessToken(), "requester-client", "secret", null, OAuth2Constants.REFRESH_TOKEN_TYPE);
assertEquals(Response.Status.OK.getStatusCode(), tokenExchangeResponse1.getStatusCode());
tokenExchangeResponse2 = tokenExchange(tokenExchangeResponse1.getAccessToken(), "requester-client-2", "secret", null, Collections.singletonMap(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.REFRESH_TOKEN_TYPE));
tokenExchangeResponse2 = tokenExchange(tokenExchangeResponse1.getAccessToken(), "requester-client-2", "secret", null, OAuth2Constants.REFRESH_TOKEN_TYPE);
assertEquals(Response.Status.OK.getStatusCode(), tokenExchangeResponse2.getStatusCode());
oauth.client("subject-client", "secret");