KEYCLOAK-10065 Merge preview features test: BrokerLinkAndTokenExchangeTest
This commit is contained in:
parent
391f1bf069
commit
ccd90d5fdc
2 changed files with 294 additions and 267 deletions
|
@ -16,9 +16,16 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.testsuite.adapter.servlet;
|
package org.keycloak.testsuite.adapter.servlet;
|
||||||
|
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
|
import org.keycloak.adapters.HttpClientBuilder;
|
||||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
import org.keycloak.representations.AccessTokenResponse;
|
import org.keycloak.representations.AccessTokenResponse;
|
||||||
|
@ -31,14 +38,9 @@ import javax.servlet.http.HttpServlet;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -69,22 +71,20 @@ public class LinkAndExchangeServlet extends HttpServlet {
|
||||||
|
|
||||||
public AccessTokenResponse doTokenExchange(String realm, String token, String requestedIssuer,
|
public AccessTokenResponse doTokenExchange(String realm, String token, String requestedIssuer,
|
||||||
String clientId, String clientSecret) throws Exception {
|
String clientId, String clientSecret) throws Exception {
|
||||||
try {
|
|
||||||
|
try (CloseableHttpClient client = (CloseableHttpClient) new HttpClientBuilder().disableTrustManager().build()) {
|
||||||
String exchangeUrl = KeycloakUriBuilder.fromUri(ServletTestUtils.getAuthServerUrlBase())
|
String exchangeUrl = KeycloakUriBuilder.fromUri(ServletTestUtils.getAuthServerUrlBase())
|
||||||
.path("/auth/realms/{realm}/protocol/openid-connect/token").build(realm).toString();
|
.path("/auth/realms/{realm}/protocol/openid-connect/token").build(realm).toString();
|
||||||
|
|
||||||
URL url = new URL(exchangeUrl);
|
HttpPost post = new HttpPost(exchangeUrl);
|
||||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
||||||
conn.setRequestMethod("POST");
|
|
||||||
conn.setDoInput(true);
|
|
||||||
conn.setDoOutput(true);
|
|
||||||
HashMap<String, String> parameters = new HashMap<>();
|
HashMap<String, String> parameters = new HashMap<>();
|
||||||
|
|
||||||
if (clientSecret != null) {
|
if (clientSecret != null) {
|
||||||
String authorization = BasicAuthHelper.createHeader(clientId, clientSecret);
|
String authorization = BasicAuthHelper.createHeader(clientId, clientSecret);
|
||||||
conn.setRequestProperty(HttpHeaders.AUTHORIZATION, authorization);
|
post.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED.toString());
|
||||||
|
post.setHeader(HttpHeaders.AUTHORIZATION, authorization);
|
||||||
} else {
|
} else {
|
||||||
parameters.put("client_id", clientId);
|
parameters.put("client_id", clientId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parameters.put(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE);
|
parameters.put(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE);
|
||||||
|
@ -92,27 +92,15 @@ public class LinkAndExchangeServlet extends HttpServlet {
|
||||||
parameters.put(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE);
|
parameters.put(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE);
|
||||||
parameters.put(OAuth2Constants.REQUESTED_ISSUER, requestedIssuer);
|
parameters.put(OAuth2Constants.REQUESTED_ISSUER, requestedIssuer);
|
||||||
|
|
||||||
OutputStream os = conn.getOutputStream();
|
post.setEntity(new StringEntity(getPostDataString(parameters)));
|
||||||
BufferedWriter writer = new BufferedWriter(
|
HttpResponse response = client.execute(post);
|
||||||
new OutputStreamWriter(os, "UTF-8"));
|
int statusCode = response.getStatusLine().getStatusCode();
|
||||||
writer.write(getPostDataString(parameters));
|
|
||||||
|
|
||||||
writer.flush();
|
|
||||||
writer.close();
|
|
||||||
os.close();
|
|
||||||
if (conn.getResponseCode() == 200) {
|
|
||||||
AccessTokenResponse tokenResponse = JsonSerialization.readValue(conn.getInputStream(), AccessTokenResponse.class);
|
|
||||||
conn.getInputStream().close();
|
|
||||||
return tokenResponse;
|
|
||||||
} else if (conn.getResponseCode() == 400) {
|
|
||||||
AccessTokenResponse tokenResponse = JsonSerialization.readValue(conn.getErrorStream(), AccessTokenResponse.class);
|
|
||||||
conn.getErrorStream().close();
|
|
||||||
return tokenResponse;
|
|
||||||
|
|
||||||
|
if (statusCode == 200 || statusCode == 400) {
|
||||||
|
return JsonSerialization.readValue(EntityUtils.toString(response.getEntity()), AccessTokenResponse.class);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Unknown error!");
|
throw new RuntimeException("Unknown error!");
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@ import org.jboss.arquillian.container.test.api.TargetsContainer;
|
||||||
import org.jboss.arquillian.graphene.page.Page;
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.admin.client.resource.RealmResource;
|
import org.keycloak.admin.client.resource.RealmResource;
|
||||||
|
@ -59,6 +59,7 @@ import org.keycloak.testsuite.ProfileAssume;
|
||||||
import org.keycloak.testsuite.adapter.AbstractAdapterTest;
|
import org.keycloak.testsuite.adapter.AbstractAdapterTest;
|
||||||
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
|
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
|
||||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||||
|
import org.keycloak.testsuite.arquillian.annotation.UncaughtServerErrorExpected;
|
||||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||||
import org.keycloak.testsuite.broker.BrokerTestTools;
|
import org.keycloak.testsuite.broker.BrokerTestTools;
|
||||||
import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
|
import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
|
||||||
|
@ -84,6 +85,7 @@ import java.net.URL;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.keycloak.testsuite.Assert.assertEquals;
|
||||||
import static org.keycloak.testsuite.admin.ApiUtil.createUserAndResetPasswordWithAdminClient;
|
import static org.keycloak.testsuite.admin.ApiUtil.createUserAndResetPasswordWithAdminClient;
|
||||||
import static org.keycloak.testsuite.arquillian.DeploymentTargetModifier.AUTH_SERVER_CURRENT;
|
import static org.keycloak.testsuite.arquillian.DeploymentTargetModifier.AUTH_SERVER_CURRENT;
|
||||||
|
|
||||||
|
@ -187,7 +189,6 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest
|
||||||
|
|
||||||
testRealms.add(realm);
|
testRealms.add(realm);
|
||||||
|
|
||||||
|
|
||||||
realm = new RealmRepresentation();
|
realm = new RealmRepresentation();
|
||||||
realm.setRealm(PARENT_IDP);
|
realm.setRealm(PARENT_IDP);
|
||||||
realm.setEnabled(true);
|
realm.setEnabled(true);
|
||||||
|
@ -200,17 +201,36 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest
|
||||||
parentApp.setFullScopeAllowed(true);
|
parentApp.setFullScopeAllowed(true);
|
||||||
realm.setClients(new LinkedList<>());
|
realm.setClients(new LinkedList<>());
|
||||||
realm.getClients().add(parentApp);
|
realm.getClients().add(parentApp);
|
||||||
|
|
||||||
testRealms.add(realm);
|
testRealms.add(realm);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@Before
|
||||||
public static void enabled() {
|
public void enableFeature() throws Exception {
|
||||||
ProfileAssume.assumeFeatureEnabled(Profile.Feature.TOKEN_EXCHANGE);
|
try {
|
||||||
|
addIdpUser();
|
||||||
|
addChildUser();
|
||||||
|
createBroker();
|
||||||
|
|
||||||
|
checkFeature(Response.Status.NOT_IMPLEMENTED.getStatusCode());
|
||||||
|
Response response = testingClient.testing().enableFeature(Profile.Feature.TOKEN_EXCHANGE.toString());
|
||||||
|
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
|
||||||
|
checkFeature(Response.Status.OK.getStatusCode());
|
||||||
|
|
||||||
|
ProfileAssume.assumeFeatureEnabled(Profile.Feature.TOKEN_EXCHANGE);
|
||||||
|
} catch (Exception e) {
|
||||||
|
disableFeature();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void disableFeature() throws Exception {
|
||||||
|
Response response = testingClient.testing().disableFeature(Profile.Feature.TOKEN_EXCHANGE.toString());
|
||||||
|
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
|
||||||
|
checkFeature(Response.Status.NOT_IMPLEMENTED.getStatusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
|
||||||
public void addIdpUser() {
|
public void addIdpUser() {
|
||||||
RealmResource realm = adminClient.realms().realm(PARENT_IDP);
|
RealmResource realm = adminClient.realms().realm(PARENT_IDP);
|
||||||
UserRepresentation user = new UserRepresentation();
|
UserRepresentation user = new UserRepresentation();
|
||||||
|
@ -226,8 +246,6 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest
|
||||||
|
|
||||||
private String childUserId = null;
|
private String childUserId = null;
|
||||||
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void addChildUser() {
|
public void addChildUser() {
|
||||||
RealmResource realm = adminClient.realms().realm(CHILD_IDP);
|
RealmResource realm = adminClient.realms().realm(CHILD_IDP);
|
||||||
UserRepresentation user = new UserRepresentation();
|
UserRepresentation user = new UserRepresentation();
|
||||||
|
@ -307,7 +325,7 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest
|
||||||
idp.setStoreToken(true);
|
idp.setStoreToken(true);
|
||||||
realm.updateIdentityProvider(idp);
|
realm.updateIdentityProvider(idp);
|
||||||
}
|
}
|
||||||
@Before
|
|
||||||
public void createBroker() {
|
public void createBroker() {
|
||||||
createParentChild();
|
createParentChild();
|
||||||
testingClient.server().run(BrokerLinkAndTokenExchangeTest::setupRealm);
|
testingClient.server().run(BrokerLinkAndTokenExchangeTest::setupRealm);
|
||||||
|
@ -319,9 +337,9 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@UncaughtServerErrorExpected
|
||||||
public void testAccountLink() throws Exception {
|
public void testAccountLink() throws Exception {
|
||||||
testingClient.server().run(BrokerLinkAndTokenExchangeTest::turnOnTokenStore);
|
testingClient.server().run(BrokerLinkAndTokenExchangeTest::turnOnTokenStore);
|
||||||
|
|
||||||
RealmResource realm = adminClient.realms().realm(CHILD_IDP);
|
RealmResource realm = adminClient.realms().realm(CHILD_IDP);
|
||||||
List<FederatedIdentityRepresentation> links = realm.users().get(childUserId).getFederatedIdentity();
|
List<FederatedIdentityRepresentation> links = realm.users().get(childUserId).getFederatedIdentity();
|
||||||
Assert.assertTrue(links.isEmpty());
|
Assert.assertTrue(links.isEmpty());
|
||||||
|
@ -349,74 +367,76 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest
|
||||||
Assert.assertFalse(links.isEmpty());
|
Assert.assertFalse(links.isEmpty());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// do exchange
|
// do exchange
|
||||||
|
|
||||||
String accessToken = oauth.doGrantAccessTokenRequest(CHILD_IDP, "child", "password", null, ClientApp.DEPLOYMENT_NAME, "password").getAccessToken();
|
String accessToken = oauth.doGrantAccessTokenRequest(CHILD_IDP, "child", "password", null, ClientApp.DEPLOYMENT_NAME, "password").getAccessToken();
|
||||||
Client httpClient = ClientBuilder.newClient();
|
Client httpClient = ClientBuilder.newClient();
|
||||||
|
try {
|
||||||
|
WebTarget exchangeUrl = childTokenExchangeWebTarget(httpClient);
|
||||||
|
System.out.println("Exchange url: " + exchangeUrl.getUri().toString());
|
||||||
|
|
||||||
WebTarget exchangeUrl = childTokenExchangeWebTarget(httpClient);
|
Response response = exchangeUrl.request()
|
||||||
System.out.println("Exchange url: " + exchangeUrl.getUri().toString());
|
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||||
|
.post(Entity.form(
|
||||||
|
new Form()
|
||||||
|
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||||
|
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||||
|
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE)
|
||||||
|
.param(OAuth2Constants.REQUESTED_ISSUER, PARENT_IDP)
|
||||||
|
|
||||||
Response response = exchangeUrl.request()
|
));
|
||||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
Assert.assertEquals(200, response.getStatus());
|
||||||
.post(Entity.form(
|
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||||
new Form()
|
response.close();
|
||||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
String externalToken = tokenResponse.getToken();
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
Assert.assertNotNull(externalToken);
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE)
|
Assert.assertTrue(tokenResponse.getExpiresIn() > 0);
|
||||||
.param(OAuth2Constants.REQUESTED_ISSUER, PARENT_IDP)
|
setTimeOffset((int) tokenResponse.getExpiresIn() + 1);
|
||||||
|
|
||||||
));
|
// test that token refresh happens
|
||||||
Assert.assertEquals(200, response.getStatus());
|
|
||||||
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
|
||||||
response.close();
|
|
||||||
String externalToken = tokenResponse.getToken();
|
|
||||||
Assert.assertNotNull(externalToken);
|
|
||||||
Assert.assertTrue(tokenResponse.getExpiresIn() > 0);
|
|
||||||
setTimeOffset((int)tokenResponse.getExpiresIn() + 1);
|
|
||||||
|
|
||||||
// test that token refresh happens
|
// get access token again because we may have timed out
|
||||||
|
accessToken = oauth.doGrantAccessTokenRequest(CHILD_IDP, "child", "password", null, ClientApp.DEPLOYMENT_NAME, "password").getAccessToken();
|
||||||
|
response = exchangeUrl.request()
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||||
|
.post(Entity.form(
|
||||||
|
new Form()
|
||||||
|
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||||
|
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||||
|
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE)
|
||||||
|
.param(OAuth2Constants.REQUESTED_ISSUER, PARENT_IDP)
|
||||||
|
|
||||||
// get access token again because we may have timed out
|
));
|
||||||
accessToken = oauth.doGrantAccessTokenRequest(CHILD_IDP, "child", "password", null, ClientApp.DEPLOYMENT_NAME, "password").getAccessToken();
|
Assert.assertEquals(200, response.getStatus());
|
||||||
response = exchangeUrl.request()
|
tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
response.close();
|
||||||
.post(Entity.form(
|
Assert.assertNotEquals(externalToken, tokenResponse.getToken());
|
||||||
new Form()
|
|
||||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE)
|
|
||||||
.param(OAuth2Constants.REQUESTED_ISSUER, PARENT_IDP)
|
|
||||||
|
|
||||||
));
|
// test direct exchange
|
||||||
Assert.assertEquals(200, response.getStatus());
|
response = exchangeUrl.request()
|
||||||
tokenResponse = response.readEntity(AccessTokenResponse.class);
|
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader("direct-exchanger", "secret"))
|
||||||
response.close();
|
.post(Entity.form(
|
||||||
Assert.assertNotEquals(externalToken, tokenResponse.getToken());
|
new Form()
|
||||||
|
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||||
|
.param(OAuth2Constants.REQUESTED_SUBJECT, "child")
|
||||||
|
.param(OAuth2Constants.REQUESTED_ISSUER, PARENT_IDP)
|
||||||
|
|
||||||
// test direct exchange
|
));
|
||||||
response = exchangeUrl.request()
|
Assert.assertEquals(200, response.getStatus());
|
||||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader("direct-exchanger", "secret"))
|
tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||||
.post(Entity.form(
|
response.close();
|
||||||
new Form()
|
Assert.assertNotEquals(externalToken, tokenResponse.getToken());
|
||||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
|
||||||
.param(OAuth2Constants.REQUESTED_SUBJECT, "child")
|
|
||||||
.param(OAuth2Constants.REQUESTED_ISSUER, PARENT_IDP)
|
|
||||||
|
|
||||||
));
|
|
||||||
Assert.assertEquals(200, response.getStatus());
|
|
||||||
tokenResponse = response.readEntity(AccessTokenResponse.class);
|
|
||||||
response.close();
|
|
||||||
Assert.assertNotEquals(externalToken, tokenResponse.getToken());
|
|
||||||
|
|
||||||
|
|
||||||
logoutAll();
|
logoutAll();
|
||||||
|
|
||||||
|
|
||||||
realm.users().get(childUserId).removeFederatedIdentity(PARENT_IDP);
|
realm.users().get(childUserId).removeFederatedIdentity(PARENT_IDP);
|
||||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||||
Assert.assertTrue(links.isEmpty());
|
Assert.assertTrue(links.isEmpty());
|
||||||
|
} finally {
|
||||||
|
httpClient.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected WebTarget childTokenExchangeWebTarget(Client httpClient) {
|
protected WebTarget childTokenExchangeWebTarget(Client httpClient) {
|
||||||
|
@ -443,6 +463,7 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@UncaughtServerErrorExpected
|
||||||
public void testAccountLinkNoTokenStore() throws Exception {
|
public void testAccountLinkNoTokenStore() throws Exception {
|
||||||
testingClient.server().run(BrokerLinkAndTokenExchangeTest::turnOffTokenStore);
|
testingClient.server().run(BrokerLinkAndTokenExchangeTest::turnOffTokenStore);
|
||||||
|
|
||||||
|
@ -472,7 +493,6 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest
|
||||||
Assert.assertFalse(links.isEmpty());
|
Assert.assertFalse(links.isEmpty());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
logoutAll();
|
logoutAll();
|
||||||
|
|
||||||
|
|
||||||
|
@ -488,6 +508,7 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
|
@UncaughtServerErrorExpected
|
||||||
public void testExportImport() throws Exception {
|
public void testExportImport() throws Exception {
|
||||||
testExternalExchange();
|
testExternalExchange();
|
||||||
testingClient.testing().exportImport().setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
|
testingClient.testing().exportImport().setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
|
||||||
|
@ -507,219 +528,190 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest
|
||||||
testExternalExchange();
|
testExternalExchange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@UncaughtServerErrorExpected
|
||||||
public void testExternalExchange() throws Exception {
|
public void testExternalExchange() throws Exception {
|
||||||
|
|
||||||
RealmResource childRealm = adminClient.realms().realm(CHILD_IDP);
|
RealmResource childRealm = adminClient.realms().realm(CHILD_IDP);
|
||||||
|
|
||||||
String accessToken = oauth.doGrantAccessTokenRequest(PARENT_IDP, PARENT2_USERNAME, "password", null, PARENT_CLIENT, "password").getAccessToken();
|
String accessToken = oauth.doGrantAccessTokenRequest(PARENT_IDP, PARENT2_USERNAME, "password", null, PARENT_CLIENT, "password").getAccessToken();
|
||||||
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||||
|
|
||||||
Client httpClient = ClientBuilder.newClient();
|
Client httpClient = ClientBuilder.newClient();
|
||||||
WebTarget exchangeUrl = childTokenExchangeWebTarget(httpClient);
|
try {
|
||||||
System.out.println("Exchange url: " + exchangeUrl.getUri().toString());
|
WebTarget exchangeUrl = childTokenExchangeWebTarget(httpClient);
|
||||||
|
System.out.println("Exchange url: " + exchangeUrl.getUri().toString());
|
||||||
|
|
||||||
|
checkFeature(200);
|
||||||
|
|
||||||
{
|
|
||||||
IdentityProviderRepresentation rep = adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).toRepresentation();
|
IdentityProviderRepresentation rep = adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).toRepresentation();
|
||||||
rep.getConfig().put(OIDCIdentityProviderConfig.VALIDATE_SIGNATURE, String.valueOf(false));
|
rep.getConfig().put(OIDCIdentityProviderConfig.VALIDATE_SIGNATURE, String.valueOf(true));
|
||||||
|
rep.getConfig().put(OIDCIdentityProviderConfig.USE_JWKS_URL, String.valueOf(true));
|
||||||
|
rep.getConfig().put(OIDCIdentityProviderConfig.JWKS_URL, parentJwksUrl());
|
||||||
|
String parentIssuer = UriBuilder.fromUri(OAuthClient.AUTH_SERVER_ROOT)
|
||||||
|
.path("/realms")
|
||||||
|
.path(PARENT_IDP)
|
||||||
|
.build().toString();
|
||||||
|
rep.getConfig().put("issuer", parentIssuer);
|
||||||
adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).update(rep);
|
adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).update(rep);
|
||||||
// test user info validation.
|
|
||||||
Response response = exchangeUrl.request()
|
|
||||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
|
||||||
.post(Entity.form(
|
|
||||||
new Form()
|
|
||||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
|
||||||
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
|
||||||
|
|
||||||
));
|
String exchangedUserId = null;
|
||||||
Assert.assertEquals(200, response.getStatus());
|
String exchangedUsername = null;
|
||||||
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
|
||||||
String exchangedAccessToken = tokenResponse.getToken();
|
|
||||||
Assert.assertNotNull(exchangedAccessToken);
|
|
||||||
response.close();
|
|
||||||
|
|
||||||
Assert.assertEquals(1, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
{
|
||||||
|
// test signature validation
|
||||||
|
Response response = exchangeUrl.request()
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||||
|
.post(Entity.form(
|
||||||
|
new Form()
|
||||||
|
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||||
|
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||||
|
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
||||||
|
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
||||||
|
|
||||||
// test logout
|
));
|
||||||
response = childLogoutWebTarget(httpClient)
|
Assert.assertEquals(200, response.getStatus());
|
||||||
.queryParam("id_token_hint", exchangedAccessToken)
|
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||||
.request()
|
String exchangedAccessToken = tokenResponse.getToken();
|
||||||
.get();
|
JWSInput jws = new JWSInput(tokenResponse.getToken());
|
||||||
response.close();
|
AccessToken token = jws.readJsonContent(AccessToken.class);
|
||||||
|
response.close();
|
||||||
|
|
||||||
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
exchangedUserId = token.getSubject();
|
||||||
|
exchangedUsername = token.getPreferredUsername();
|
||||||
|
|
||||||
}
|
System.out.println("exchangedUserId: " + exchangedUserId);
|
||||||
IdentityProviderRepresentation rep = adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).toRepresentation();
|
System.out.println("exchangedUsername: " + exchangedUsername);
|
||||||
rep.getConfig().put(OIDCIdentityProviderConfig.VALIDATE_SIGNATURE, String.valueOf(true));
|
|
||||||
rep.getConfig().put(OIDCIdentityProviderConfig.USE_JWKS_URL, String.valueOf(true));
|
|
||||||
rep.getConfig().put(OIDCIdentityProviderConfig.JWKS_URL, parentJwksUrl());
|
|
||||||
String parentIssuer = UriBuilder.fromUri(OAuthClient.AUTH_SERVER_ROOT)
|
|
||||||
.path("/realms")
|
|
||||||
.path(PARENT_IDP)
|
|
||||||
.build().toString();
|
|
||||||
rep.getConfig().put("issuer", parentIssuer);
|
|
||||||
adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).update(rep);
|
|
||||||
|
|
||||||
String exchangedUserId = null;
|
|
||||||
String exchangedUsername = null;
|
|
||||||
|
|
||||||
{
|
|
||||||
// test signature validation
|
|
||||||
Response response = exchangeUrl.request()
|
|
||||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
|
||||||
.post(Entity.form(
|
|
||||||
new Form()
|
|
||||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
|
||||||
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
|
||||||
|
|
||||||
));
|
|
||||||
Assert.assertEquals(200, response.getStatus());
|
|
||||||
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
|
||||||
String exchangedAccessToken = tokenResponse.getToken();
|
|
||||||
JWSInput jws = new JWSInput(tokenResponse.getToken());
|
|
||||||
AccessToken token = jws.readJsonContent(AccessToken.class);
|
|
||||||
response.close();
|
|
||||||
|
|
||||||
exchangedUserId = token.getSubject();
|
|
||||||
exchangedUsername = token.getPreferredUsername();
|
|
||||||
|
|
||||||
System.out.println("exchangedUserId: " + exchangedUserId);
|
|
||||||
System.out.println("exchangedUsername: " + exchangedUsername);
|
|
||||||
|
|
||||||
|
|
||||||
// test that we can exchange back to external token
|
// test that we can exchange back to external token
|
||||||
response = exchangeUrl.request()
|
response = exchangeUrl.request()
|
||||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||||
.post(Entity.form(
|
.post(Entity.form(
|
||||||
new Form()
|
new Form()
|
||||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN, tokenResponse.getToken())
|
.param(OAuth2Constants.SUBJECT_TOKEN, tokenResponse.getToken())
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE)
|
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE)
|
||||||
.param(OAuth2Constants.REQUESTED_ISSUER, PARENT_IDP)
|
.param(OAuth2Constants.REQUESTED_ISSUER, PARENT_IDP)
|
||||||
|
|
||||||
));
|
));
|
||||||
Assert.assertEquals(200, response.getStatus());
|
Assert.assertEquals(200, response.getStatus());
|
||||||
tokenResponse = response.readEntity(AccessTokenResponse.class);
|
tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||||
Assert.assertEquals(accessToken, tokenResponse.getToken());
|
Assert.assertEquals(accessToken, tokenResponse.getToken());
|
||||||
response.close();
|
response.close();
|
||||||
|
|
||||||
Assert.assertEquals(1, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
Assert.assertEquals(1, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||||
|
|
||||||
// test logout
|
// test logout
|
||||||
response = childLogoutWebTarget(httpClient)
|
response = childLogoutWebTarget(httpClient)
|
||||||
.queryParam("id_token_hint", exchangedAccessToken)
|
.queryParam("id_token_hint", exchangedAccessToken)
|
||||||
.request()
|
.request()
|
||||||
.get();
|
.get();
|
||||||
response.close();
|
response.close();
|
||||||
|
|
||||||
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||||
|
|
||||||
|
|
||||||
List<FederatedIdentityRepresentation> links = childRealm.users().get(exchangedUserId).getFederatedIdentity();
|
List<FederatedIdentityRepresentation> links = childRealm.users().get(exchangedUserId).getFederatedIdentity();
|
||||||
Assert.assertEquals(1, links.size());
|
Assert.assertEquals(1, links.size());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// check that we can request an exchange again and that the previously linked user is obtained
|
// check that we can request an exchange again and that the previously linked user is obtained
|
||||||
Response response = exchangeUrl.request()
|
Response response = exchangeUrl.request()
|
||||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||||
.post(Entity.form(
|
.post(Entity.form(
|
||||||
new Form()
|
new Form()
|
||||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
||||||
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
||||||
|
|
||||||
));
|
));
|
||||||
Assert.assertEquals(200, response.getStatus());
|
Assert.assertEquals(200, response.getStatus());
|
||||||
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||||
String exchangedAccessToken = tokenResponse.getToken();
|
String exchangedAccessToken = tokenResponse.getToken();
|
||||||
JWSInput jws = new JWSInput(tokenResponse.getToken());
|
JWSInput jws = new JWSInput(tokenResponse.getToken());
|
||||||
AccessToken token = jws.readJsonContent(AccessToken.class);
|
AccessToken token = jws.readJsonContent(AccessToken.class);
|
||||||
response.close();
|
response.close();
|
||||||
|
|
||||||
String exchanged2UserId = token.getSubject();
|
String exchanged2UserId = token.getSubject();
|
||||||
String exchanged2Username = token.getPreferredUsername();
|
String exchanged2Username = token.getPreferredUsername();
|
||||||
|
|
||||||
// assert that we get the same linked account as was previously imported
|
// assert that we get the same linked account as was previously imported
|
||||||
|
|
||||||
Assert.assertEquals(exchangedUserId, exchanged2UserId);
|
Assert.assertEquals(exchangedUserId, exchanged2UserId);
|
||||||
Assert.assertEquals(exchangedUsername, exchanged2Username);
|
Assert.assertEquals(exchangedUsername, exchanged2Username);
|
||||||
|
|
||||||
// test logout
|
// test logout
|
||||||
response = childLogoutWebTarget(httpClient)
|
response = childLogoutWebTarget(httpClient)
|
||||||
.queryParam("id_token_hint", exchangedAccessToken)
|
.queryParam("id_token_hint", exchangedAccessToken)
|
||||||
.request()
|
.request()
|
||||||
.get();
|
.get();
|
||||||
response.close();
|
response.close();
|
||||||
|
|
||||||
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||||
|
|
||||||
|
|
||||||
List<FederatedIdentityRepresentation> links = childRealm.users().get(exchangedUserId).getFederatedIdentity();
|
List<FederatedIdentityRepresentation> links = childRealm.users().get(exchangedUserId).getFederatedIdentity();
|
||||||
Assert.assertEquals(1, links.size());
|
Assert.assertEquals(1, links.size());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// check that we can exchange without specifying an SUBJECT_ISSUER
|
// check that we can exchange without specifying an SUBJECT_ISSUER
|
||||||
Response response = exchangeUrl.request()
|
Response response = exchangeUrl.request()
|
||||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||||
.post(Entity.form(
|
.post(Entity.form(
|
||||||
new Form()
|
new Form()
|
||||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
||||||
|
|
||||||
));
|
));
|
||||||
Assert.assertEquals(200, response.getStatus());
|
Assert.assertEquals(200, response.getStatus());
|
||||||
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||||
String exchangedAccessToken = tokenResponse.getToken();
|
String exchangedAccessToken = tokenResponse.getToken();
|
||||||
JWSInput jws = new JWSInput(tokenResponse.getToken());
|
JWSInput jws = new JWSInput(tokenResponse.getToken());
|
||||||
AccessToken token = jws.readJsonContent(AccessToken.class);
|
AccessToken token = jws.readJsonContent(AccessToken.class);
|
||||||
response.close();
|
response.close();
|
||||||
|
|
||||||
String exchanged2UserId = token.getSubject();
|
String exchanged2UserId = token.getSubject();
|
||||||
String exchanged2Username = token.getPreferredUsername();
|
String exchanged2Username = token.getPreferredUsername();
|
||||||
|
|
||||||
// assert that we get the same linked account as was previously imported
|
// assert that we get the same linked account as was previously imported
|
||||||
|
|
||||||
Assert.assertEquals(exchangedUserId, exchanged2UserId);
|
Assert.assertEquals(exchangedUserId, exchanged2UserId);
|
||||||
Assert.assertEquals(exchangedUsername, exchanged2Username);
|
Assert.assertEquals(exchangedUsername, exchanged2Username);
|
||||||
|
|
||||||
// test logout
|
// test logout
|
||||||
response = childLogoutWebTarget(httpClient)
|
response = childLogoutWebTarget(httpClient)
|
||||||
.queryParam("id_token_hint", exchangedAccessToken)
|
.queryParam("id_token_hint", exchangedAccessToken)
|
||||||
.request()
|
.request()
|
||||||
.get();
|
.get();
|
||||||
response.close();
|
response.close();
|
||||||
|
|
||||||
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||||
|
|
||||||
|
|
||||||
List<FederatedIdentityRepresentation> links = childRealm.users().get(exchangedUserId).getFederatedIdentity();
|
List<FederatedIdentityRepresentation> links = childRealm.users().get(exchangedUserId).getFederatedIdentity();
|
||||||
Assert.assertEquals(1, links.size());
|
Assert.assertEquals(1, links.size());
|
||||||
}
|
}
|
||||||
// cleanup remove the user
|
// cleanup remove the user
|
||||||
childRealm.users().get(exchangedUserId).remove();
|
childRealm.users().get(exchangedUserId).remove();
|
||||||
|
|
||||||
{
|
{
|
||||||
// test unauthorized client gets 403
|
// test unauthorized client gets 403
|
||||||
Response response = exchangeUrl.request()
|
Response response = exchangeUrl.request()
|
||||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(UNAUTHORIZED_CHILD_CLIENT, "password"))
|
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(UNAUTHORIZED_CHILD_CLIENT, "password"))
|
||||||
.post(Entity.form(
|
.post(Entity.form(
|
||||||
new Form()
|
new Form()
|
||||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
||||||
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
||||||
|
|
||||||
));
|
));
|
||||||
Assert.assertEquals(403, response.getStatus());
|
Assert.assertEquals(403, response.getStatus());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
httpClient.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,6 +728,53 @@ public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest
|
||||||
WaitUtils.waitForPageToLoad();
|
WaitUtils.waitForPageToLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkFeature(int statusCode) throws Exception {
|
||||||
|
String accessToken = oauth.doGrantAccessTokenRequest(PARENT_IDP, PARENT2_USERNAME, "password", null, PARENT_CLIENT, "password").getAccessToken();
|
||||||
|
|
||||||
|
if (statusCode != Response.Status.NOT_IMPLEMENTED.getStatusCode()) {
|
||||||
|
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
Client httpClient = ClientBuilder.newClient();
|
||||||
|
try {
|
||||||
|
WebTarget exchangeUrl = childTokenExchangeWebTarget(httpClient);
|
||||||
|
{
|
||||||
|
IdentityProviderRepresentation rep = adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).toRepresentation();
|
||||||
|
rep.getConfig().put(OIDCIdentityProviderConfig.VALIDATE_SIGNATURE, String.valueOf(false));
|
||||||
|
adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).update(rep);
|
||||||
|
// test user info validation.
|
||||||
|
Response response = exchangeUrl.request()
|
||||||
|
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||||
|
.post(Entity.form(
|
||||||
|
new Form()
|
||||||
|
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||||
|
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||||
|
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
||||||
|
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
||||||
|
|
||||||
|
));
|
||||||
|
Assert.assertEquals(statusCode, response.getStatus());
|
||||||
|
|
||||||
|
if (statusCode != Response.Status.NOT_IMPLEMENTED.getStatusCode()) {
|
||||||
|
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||||
|
String exchangedAccessToken = tokenResponse.getToken();
|
||||||
|
Assert.assertNotNull(exchangedAccessToken);
|
||||||
|
response.close();
|
||||||
|
|
||||||
|
Assert.assertEquals(1, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||||
|
|
||||||
|
// test logout
|
||||||
|
response = childLogoutWebTarget(httpClient)
|
||||||
|
.queryParam("id_token_hint", exchangedAccessToken)
|
||||||
|
.request()
|
||||||
|
.get();
|
||||||
|
response.close();
|
||||||
|
|
||||||
|
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
httpClient.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue