KEYCLOAK-10063 Merge preview features test: ClientTokenExchangeTest
This commit is contained in:
parent
0042726dd8
commit
a6e53b3f1c
3 changed files with 210 additions and 81 deletions
|
@ -20,6 +20,7 @@ package org.keycloak.testsuite.rest;
|
|||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.spi.BadRequestException;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.events.Event;
|
||||
|
@ -278,18 +279,18 @@ public class TestingResourceProvider implements RealmResourceProvider {
|
|||
|
||||
/**
|
||||
* Query events
|
||||
*
|
||||
* <p>
|
||||
* Returns all events, or filters them based on URL query parameters listed here
|
||||
*
|
||||
* @param realmId The realm
|
||||
* @param types The types of events to return
|
||||
* @param client App or oauth client name
|
||||
* @param user User id
|
||||
* @param dateFrom From date
|
||||
* @param dateTo To date
|
||||
* @param ipAddress IP address
|
||||
* @param realmId The realm
|
||||
* @param types The types of events to return
|
||||
* @param client App or oauth client name
|
||||
* @param user User id
|
||||
* @param dateFrom From date
|
||||
* @param dateTo To date
|
||||
* @param ipAddress IP address
|
||||
* @param firstResult Paging offset
|
||||
* @param maxResults Paging size
|
||||
* @param maxResults Paging size
|
||||
* @return
|
||||
*/
|
||||
@Path("query-events")
|
||||
|
@ -297,9 +298,9 @@ public class TestingResourceProvider implements RealmResourceProvider {
|
|||
@NoCache
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public List<EventRepresentation> queryEvents(@QueryParam("realmId") String realmId, @QueryParam("type") List<String> types, @QueryParam("client") String client,
|
||||
@QueryParam("user") String user, @QueryParam("dateFrom") String dateFrom, @QueryParam("dateTo") String dateTo,
|
||||
@QueryParam("ipAddress") String ipAddress, @QueryParam("first") Integer firstResult,
|
||||
@QueryParam("max") Integer maxResults) {
|
||||
@QueryParam("user") String user, @QueryParam("dateFrom") String dateFrom, @QueryParam("dateTo") String dateTo,
|
||||
@QueryParam("ipAddress") String ipAddress, @QueryParam("first") Integer firstResult,
|
||||
@QueryParam("max") Integer maxResults) {
|
||||
|
||||
EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
|
||||
|
||||
|
@ -325,12 +326,12 @@ public class TestingResourceProvider implements RealmResourceProvider {
|
|||
query.user(user);
|
||||
}
|
||||
|
||||
if(dateFrom != null) {
|
||||
if (dateFrom != null) {
|
||||
Date from = formatDate(dateFrom, "Date(From)");
|
||||
query.fromDate(from);
|
||||
}
|
||||
|
||||
if(dateTo != null) {
|
||||
if (dateTo != null) {
|
||||
Date to = formatDate(dateTo, "Date(To)");
|
||||
query.toDate(to);
|
||||
}
|
||||
|
@ -429,10 +430,10 @@ public class TestingResourceProvider implements RealmResourceProvider {
|
|||
@NoCache
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public List<AdminEventRepresentation> getAdminEvents(@QueryParam("realmId") String realmId, @QueryParam("operationTypes") List<String> operationTypes, @QueryParam("authRealm") String authRealm, @QueryParam("authClient") String authClient,
|
||||
@QueryParam("authUser") String authUser, @QueryParam("authIpAddress") String authIpAddress,
|
||||
@QueryParam("resourcePath") String resourcePath, @QueryParam("dateFrom") String dateFrom,
|
||||
@QueryParam("dateTo") String dateTo, @QueryParam("first") Integer firstResult,
|
||||
@QueryParam("max") Integer maxResults) {
|
||||
@QueryParam("authUser") String authUser, @QueryParam("authIpAddress") String authIpAddress,
|
||||
@QueryParam("resourcePath") String resourcePath, @QueryParam("dateFrom") String dateFrom,
|
||||
@QueryParam("dateTo") String dateTo, @QueryParam("first") Integer firstResult,
|
||||
@QueryParam("max") Integer maxResults) {
|
||||
|
||||
EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
|
||||
AdminEventQuery query = eventStore.createAdminQuery();
|
||||
|
@ -469,12 +470,12 @@ public class TestingResourceProvider implements RealmResourceProvider {
|
|||
query.operation(t);
|
||||
}
|
||||
|
||||
if(dateFrom != null) {
|
||||
if (dateFrom != null) {
|
||||
Date from = formatDate(dateFrom, "Date(From)");
|
||||
query.fromTime(from);
|
||||
}
|
||||
|
||||
if(dateTo != null) {
|
||||
if (dateTo != null) {
|
||||
Date to = formatDate(dateTo, "Date(To)");
|
||||
query.toTime(to);
|
||||
}
|
||||
|
@ -618,7 +619,7 @@ public class TestingResourceProvider implements RealmResourceProvider {
|
|||
public UserRepresentation getUserByUsernameFromFedProviderFactory(@QueryParam("realmName") String realmName,
|
||||
@QueryParam("userName") String userName) {
|
||||
RealmModel realm = getRealmByName(realmName);
|
||||
DummyUserFederationProviderFactory factory = (DummyUserFederationProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, "dummy");
|
||||
DummyUserFederationProviderFactory factory = (DummyUserFederationProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, "dummy");
|
||||
UserModel user = factory.create(session, null).getUserByUsername(userName, realm);
|
||||
if (user == null) return null;
|
||||
return ModelToRepresentation.toRepresentation(session, realm, user);
|
||||
|
@ -768,7 +769,6 @@ public class TestingResourceProvider implements RealmResourceProvider {
|
|||
}
|
||||
|
||||
|
||||
|
||||
@POST
|
||||
@Path("/run-on-server")
|
||||
@Consumes(MediaType.TEXT_PLAIN_UTF_8)
|
||||
|
@ -824,6 +824,62 @@ public class TestingResourceProvider implements RealmResourceProvider {
|
|||
return new TestJavascriptResource();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/enable-feature/{feature}")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response enableFeature(@PathParam("feature") String feature) {
|
||||
|
||||
Profile.Feature featureProfile = Profile.Feature.valueOf(feature);
|
||||
|
||||
if (featureProfile == null)
|
||||
return Response.status(Response.Status.NOT_FOUND).build();
|
||||
|
||||
if (Profile.isFeatureEnabled(featureProfile))
|
||||
return Response.ok().build();
|
||||
|
||||
System.setProperty("keycloak.profile.feature." + feature.toLowerCase(), "enabled");
|
||||
|
||||
switch (featureProfile.getType()) {
|
||||
case PREVIEW:
|
||||
Profile.getPreviewFeatures().add(featureProfile);
|
||||
break;
|
||||
case EXPERIMENTAL:
|
||||
Profile.getExperimentalFeatures().add(featureProfile);
|
||||
break;
|
||||
}
|
||||
|
||||
Profile.getDisabledFeatures().remove(featureProfile);
|
||||
Profile.init();
|
||||
|
||||
if (Profile.isFeatureEnabled(featureProfile))
|
||||
return Response.ok().build();
|
||||
else
|
||||
return Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/disable-feature/{feature}")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response disableFeature(@PathParam("feature") String feature) {
|
||||
|
||||
Profile.Feature featureProfile = Profile.Feature.valueOf(feature);
|
||||
|
||||
if (featureProfile == null)
|
||||
return Response.status(Response.Status.NOT_FOUND).build();
|
||||
|
||||
if (!Profile.isFeatureEnabled(featureProfile))
|
||||
return Response.ok().build();
|
||||
|
||||
System.getProperties().remove("keycloak.profile.feature." + feature.toLowerCase());
|
||||
Profile.getDisabledFeatures().add(featureProfile);
|
||||
Profile.init();
|
||||
|
||||
if (!Profile.isFeatureEnabled(featureProfile))
|
||||
return Response.ok().build();
|
||||
else
|
||||
return Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
|
||||
private RealmModel getRealmByName(String realmName) {
|
||||
RealmProvider realmProvider = session.getProvider(RealmProvider.class);
|
||||
RealmModel realm = realmProvider.getRealmByName(realmName);
|
||||
|
|
|
@ -98,15 +98,15 @@ public interface TestingResource {
|
|||
*
|
||||
* Returns all events, or filters them based on URL query parameters listed here
|
||||
*
|
||||
* @param realmId The realm
|
||||
* @param types The types of events to return
|
||||
* @param client App or oauth client name
|
||||
* @param user User id
|
||||
* @param dateFrom From date
|
||||
* @param dateTo To date
|
||||
* @param ipAddress IP address
|
||||
* @param realmId The realm
|
||||
* @param types The types of events to return
|
||||
* @param client App or oauth client name
|
||||
* @param user User id
|
||||
* @param dateFrom From date
|
||||
* @param dateTo To date
|
||||
* @param ipAddress IP address
|
||||
* @param firstResult Paging offset
|
||||
* @param maxResults Paging size
|
||||
* @param maxResults Paging size
|
||||
* @return
|
||||
*/
|
||||
@Path("query-events")
|
||||
|
@ -140,7 +140,7 @@ public interface TestingResource {
|
|||
|
||||
/**
|
||||
* Get admin events
|
||||
*
|
||||
* <p>
|
||||
* Returns all admin events, or filters events based on URL query parameters listed here
|
||||
*
|
||||
* @param realmId
|
||||
|
@ -312,4 +312,13 @@ public interface TestingResource {
|
|||
@Produces(MediaType.TEXT_HTML_UTF_8)
|
||||
String getJavascriptTestingEnvironment();
|
||||
|
||||
@POST
|
||||
@Path("/enable-feature/{feature}")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
Response enableFeature(@PathParam("feature") String feature);
|
||||
|
||||
@POST
|
||||
@Path("/disable-feature/{feature}")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
Response disableFeature(@PathParam("feature") String feature);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ package org.keycloak.testsuite.oauth;
|
|||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
|
@ -26,15 +28,8 @@ import org.keycloak.TokenVerifier;
|
|||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ImpersonationConstants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.*;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocolFactory;
|
||||
import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
|
@ -47,6 +42,7 @@ import org.keycloak.testsuite.AbstractKeycloakTest;
|
|||
import org.keycloak.testsuite.Assert;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.ProfileAssume;
|
||||
import org.keycloak.testsuite.arquillian.annotation.UncaughtServerErrorExpected;
|
||||
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
import org.keycloak.util.BasicAuthHelper;
|
||||
|
@ -62,7 +58,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.keycloak.models.ImpersonationSessionNote.IMPERSONATOR_ID;
|
||||
import static org.keycloak.models.ImpersonationSessionNote.IMPERSONATOR_USERNAME;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||
|
@ -72,6 +68,8 @@ import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
|||
*/
|
||||
public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
||||
|
||||
private final Profile.Feature FEATURE = Profile.Feature.TOKEN_EXCHANGE;
|
||||
|
||||
@Rule
|
||||
public AssertEvents events = new AssertEvents(this);
|
||||
|
||||
|
@ -80,6 +78,30 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
return RunOnServerDeployment.create(ClientTokenExchangeTest.class);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void enableFeature() {
|
||||
// Required feature should return Status code 501 - Feature doesn't work
|
||||
testingClient.server().run(ClientTokenExchangeTest::addDirectExchanger);
|
||||
Assert.assertEquals(501, checkTokenExchange().getStatus());
|
||||
testingClient.server().run(ClientTokenExchangeTest::removeDirectExchanger);
|
||||
|
||||
// Test if required feature is enabled in Profiles.
|
||||
Response response = testingClient.testing().enableFeature(FEATURE.toString());
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
|
||||
// Test if the required feature really works.
|
||||
testingClient.server().run(ClientTokenExchangeTest::addDirectExchanger);
|
||||
Assert.assertEquals(200, checkTokenExchange().getStatus());
|
||||
testingClient.server().run(ClientTokenExchangeTest::removeDirectExchanger);
|
||||
}
|
||||
|
||||
@After
|
||||
public void disableFeature() {
|
||||
// Test if required feature is disabled.
|
||||
Response response = testingClient.testing().disableFeature(FEATURE.toString());
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation testRealmRep = new RealmRepresentation();
|
||||
|
@ -90,20 +112,14 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
}
|
||||
|
||||
public static void setupRealm(KeycloakSession session) {
|
||||
RealmModel realm = session.realms().getRealmByName(TEST);
|
||||
addDirectExchanger(session);
|
||||
|
||||
RoleModel exampleRole = realm.addRole("example");
|
||||
RealmModel realm = session.realms().getRealmByName(TEST);
|
||||
RoleModel exampleRole = realm.getRole("example");
|
||||
|
||||
AdminPermissionManagement management = AdminPermissions.management(session, realm);
|
||||
|
||||
ClientModel target = realm.addClient("target");
|
||||
target.setDirectAccessGrantsEnabled(true);
|
||||
target.setEnabled(true);
|
||||
target.setSecret("secret");
|
||||
target.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
target.setFullScopeAllowed(false);
|
||||
target.addScopeMapping(exampleRole);
|
||||
|
||||
ClientModel target = realm.getClientByClientId("target");
|
||||
assertNotNull(target);
|
||||
|
||||
RoleModel impersonateRole = management.getRealmManagementClient().getRole(ImpersonationConstants.IMPERSONATION_ROLE);
|
||||
|
||||
|
@ -119,16 +135,6 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
clientExchanger.addProtocolMapper(UserSessionNoteMapper.createUserSessionNoteMapper(IMPERSONATOR_ID));
|
||||
clientExchanger.addProtocolMapper(UserSessionNoteMapper.createUserSessionNoteMapper(IMPERSONATOR_USERNAME));
|
||||
|
||||
|
||||
ClientModel directExchanger = realm.addClient("direct-exchanger");
|
||||
directExchanger.setClientId("direct-exchanger");
|
||||
directExchanger.setPublicClient(false);
|
||||
directExchanger.setDirectAccessGrantsEnabled(true);
|
||||
directExchanger.setEnabled(true);
|
||||
directExchanger.setSecret("secret");
|
||||
directExchanger.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
directExchanger.setFullScopeAllowed(false);
|
||||
|
||||
ClientModel illegal = realm.addClient("illegal");
|
||||
illegal.setClientId("illegal");
|
||||
illegal.setPublicClient(false);
|
||||
|
@ -172,14 +178,13 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
directNoSecret.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
directNoSecret.setFullScopeAllowed(false);
|
||||
|
||||
|
||||
// permission for client to client exchange to "target" client
|
||||
management.clients().setPermissionsEnabled(target, true);
|
||||
ClientPolicyRepresentation clientRep = new ClientPolicyRepresentation();
|
||||
clientRep.setName("to");
|
||||
clientRep.addClient(clientExchanger.getId());
|
||||
clientRep.addClient(legal.getId());
|
||||
clientRep.addClient(directLegal.getId());
|
||||
|
||||
ResourceServer server = management.realmResourceServer();
|
||||
Policy clientPolicy = management.authz().getStoreFactory().getPolicyStore().create(clientRep, server);
|
||||
management.clients().exchangeToPermission(target).addAssociatedPolicy(clientPolicy);
|
||||
|
@ -189,7 +194,6 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
ClientPolicyRepresentation clientImpersonateRep = new ClientPolicyRepresentation();
|
||||
clientImpersonateRep.setName("clientImpersonators");
|
||||
clientImpersonateRep.addClient(directLegal.getId());
|
||||
clientImpersonateRep.addClient(directExchanger.getId());
|
||||
clientImpersonateRep.addClient(directPublic.getId());
|
||||
clientImpersonateRep.addClient(directNoSecret.getId());
|
||||
server = management.realmResourceServer();
|
||||
|
@ -207,12 +211,6 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
UserModel bad = session.users().addUser(realm, "bad-impersonator");
|
||||
bad.setEnabled(true);
|
||||
session.userCredentialManager().updateCredential(realm, bad, UserCredentialModel.password("password"));
|
||||
|
||||
UserModel impersonatedUser = session.users().addUser(realm, "impersonated-user");
|
||||
impersonatedUser.setEnabled(true);
|
||||
session.userCredentialManager().updateCredential(realm, impersonatedUser, UserCredentialModel.password("password"));
|
||||
impersonatedUser.grantRole(exampleRole);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -220,8 +218,8 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@UncaughtServerErrorExpected
|
||||
public void testExchange() throws Exception {
|
||||
ProfileAssume.assumeFeatureEnabled(Profile.Feature.TOKEN_EXCHANGE);
|
||||
|
||||
|
@ -229,7 +227,6 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
|
||||
oauth.realm(TEST);
|
||||
oauth.clientId("client-exchanger");
|
||||
|
||||
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("secret", "user", "password");
|
||||
String accessToken = response.getAccessToken();
|
||||
TokenVerifier<AccessToken> accessTokenVerifier = TokenVerifier.create(accessToken, AccessToken.class);
|
||||
|
@ -239,7 +236,6 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
|
||||
{
|
||||
response = oauth.doTokenExchange(TEST, accessToken, "target", "client-exchanger", "secret");
|
||||
|
||||
String exchangedTokenString = response.getAccessToken();
|
||||
TokenVerifier<AccessToken> verifier = TokenVerifier.create(exchangedTokenString, AccessToken.class);
|
||||
AccessToken exchangedToken = verifier.parse().getToken();
|
||||
|
@ -265,7 +261,9 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
Assert.assertEquals(403, response.getStatusCode());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@UncaughtServerErrorExpected
|
||||
public void testImpersonation() throws Exception {
|
||||
ProfileAssume.assumeFeatureEnabled(Profile.Feature.TOKEN_EXCHANGE);
|
||||
|
||||
|
@ -346,11 +344,10 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
Assert.assertEquals(exchangedToken.getPreferredUsername(), "impersonated-user");
|
||||
Assert.assertTrue(exchangedToken.getRealmAccess().isUserInRole("example"));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@UncaughtServerErrorExpected
|
||||
public void testBadImpersonator() throws Exception {
|
||||
ProfileAssume.assumeFeatureEnabled(Profile.Feature.TOKEN_EXCHANGE);
|
||||
|
||||
|
@ -394,6 +391,7 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@UncaughtServerErrorExpected
|
||||
public void testDirectImpersonation() throws Exception {
|
||||
ProfileAssume.assumeFeatureEnabled(Profile.Feature.TOKEN_EXCHANGE);
|
||||
|
||||
|
@ -416,7 +414,7 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
.param(OAuth2Constants.REQUESTED_SUBJECT, "impersonated-user")
|
||||
|
||||
));
|
||||
org.junit.Assert.assertEquals(200, response.getStatus());
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
AccessTokenResponse accessTokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||
response.close();
|
||||
|
||||
|
@ -440,7 +438,7 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
.param(OAuth2Constants.AUDIENCE, "target")
|
||||
|
||||
));
|
||||
org.junit.Assert.assertEquals(200, response.getStatus());
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
AccessTokenResponse accessTokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||
response.close();
|
||||
|
||||
|
@ -482,9 +480,75 @@ public class ClientTokenExchangeTest extends AbstractKeycloakTest {
|
|||
Assert.assertTrue(response.getStatus() >= 400);
|
||||
response.close();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static void addDirectExchanger(KeycloakSession session) {
|
||||
RealmModel realm = session.realms().getRealmByName(TEST);
|
||||
RoleModel exampleRole = realm.addRole("example");
|
||||
AdminPermissionManagement management = AdminPermissions.management(session, realm);
|
||||
|
||||
ClientModel target = realm.addClient("target");
|
||||
target.setName("target");
|
||||
target.setClientId("target");
|
||||
target.setDirectAccessGrantsEnabled(true);
|
||||
target.setEnabled(true);
|
||||
target.setSecret("secret");
|
||||
target.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
target.setFullScopeAllowed(false);
|
||||
target.addScopeMapping(exampleRole);
|
||||
|
||||
ClientModel directExchanger = realm.addClient("direct-exchanger");
|
||||
directExchanger.setName("direct-exchanger");
|
||||
directExchanger.setClientId("direct-exchanger");
|
||||
directExchanger.setPublicClient(false);
|
||||
directExchanger.setDirectAccessGrantsEnabled(true);
|
||||
directExchanger.setEnabled(true);
|
||||
directExchanger.setSecret("secret");
|
||||
directExchanger.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
directExchanger.setFullScopeAllowed(false);
|
||||
|
||||
// permission for client to client exchange to "target" client
|
||||
management.clients().setPermissionsEnabled(target, true);
|
||||
|
||||
ClientPolicyRepresentation clientImpersonateRep = new ClientPolicyRepresentation();
|
||||
clientImpersonateRep.setName("clientImpersonatorsDirect");
|
||||
clientImpersonateRep.addClient(directExchanger.getId());
|
||||
|
||||
ResourceServer server = management.realmResourceServer();
|
||||
Policy clientImpersonatePolicy = management.authz().getStoreFactory().getPolicyStore().create(clientImpersonateRep, server);
|
||||
management.users().setPermissionsEnabled(true);
|
||||
management.users().adminImpersonatingPermission().addAssociatedPolicy(clientImpersonatePolicy);
|
||||
management.users().adminImpersonatingPermission().setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
|
||||
|
||||
UserModel impersonatedUser = session.users().addUser(realm, "impersonated-user");
|
||||
impersonatedUser.setEnabled(true);
|
||||
session.userCredentialManager().updateCredential(realm, impersonatedUser, UserCredentialModel.password("password"));
|
||||
impersonatedUser.grantRole(exampleRole);
|
||||
}
|
||||
|
||||
private static void removeDirectExchanger(KeycloakSession session) {
|
||||
RealmModel realm = session.realms().getRealmByName(TEST);
|
||||
realm.removeClient(realm.getClientByClientId("direct-exchanger").getId());
|
||||
realm.removeClient(realm.getClientByClientId("target").getId());
|
||||
realm.removeRole(realm.getRole("example"));
|
||||
session.users().removeUser(realm, session.users().getUserByUsername("impersonated-user", realm));
|
||||
}
|
||||
|
||||
private Response checkTokenExchange() {
|
||||
Client httpClient = ClientBuilder.newClient();
|
||||
WebTarget exchangeUrl = httpClient.target(OAuthClient.AUTH_SERVER_ROOT)
|
||||
.path("/realms")
|
||||
.path(TEST)
|
||||
.path("protocol/openid-connect/token");
|
||||
|
||||
Response response = exchangeUrl.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader("direct-exchanger", "secret"))
|
||||
.post(Entity.form(
|
||||
new Form()
|
||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||
.param(OAuth2Constants.REQUESTED_SUBJECT, "impersonated-user")
|
||||
|
||||
));
|
||||
return response;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue