use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.
the class ClientTokenExchangeSAML2Test method testDirectImpersonation.
@Test
@UncaughtServerErrorExpected
public void testDirectImpersonation() throws Exception {
testingClient.server().run(ClientTokenExchangeSAML2Test::setupRealm);
Client httpClient = AdminClientUtil.createResteasyClient();
WebTarget exchangeUrl = httpClient.target(OAuthClient.AUTH_SERVER_ROOT).path("/realms").path(TEST).path("protocol/openid-connect/token");
System.out.println("Exchange url: " + exchangeUrl.getUri().toString());
// direct-legal can impersonate from token "user" to user "impersonated-user" and to "target" client
{
Response response = exchangeUrl.request().header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader("direct-legal", "secret")).post(Entity.form(new Form().param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE).param(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.SAML2_TOKEN_TYPE).param(OAuth2Constants.REQUESTED_SUBJECT, "impersonated-user").param(OAuth2Constants.AUDIENCE, SAML_SIGNED_TARGET)));
Assert.assertEquals(200, response.getStatus());
AccessTokenResponse accessTokenResponse = response.readEntity(AccessTokenResponse.class);
response.close();
String exchangedTokenString = accessTokenResponse.getToken();
String assertionXML = new String(Base64Url.decode(exchangedTokenString), "UTF-8");
// Verify issued_token_type
Assert.assertEquals(OAuth2Constants.SAML2_TOKEN_TYPE, accessTokenResponse.getOtherClaims().get(OAuth2Constants.ISSUED_TOKEN_TYPE));
// Verify assertion
Element assertionElement = DocumentUtil.getDocument(assertionXML).getDocumentElement();
Assert.assertTrue(AssertionUtil.isSignedElement(assertionElement));
AssertionType assertion = (AssertionType) SAMLParser.getInstance().parse(assertionElement);
Assert.assertTrue(AssertionUtil.isSignatureValid(assertionElement, publicKeyFromString(REALM_PUBLIC_KEY)));
// Audience
AudienceRestrictionType aud = (AudienceRestrictionType) assertion.getConditions().getConditions().get(0);
Assert.assertEquals(SAML_SIGNED_TARGET, aud.getAudience().get(0).toString());
// NameID
Assert.assertEquals("impersonated-user", ((NameIDType) assertion.getSubject().getSubType().getBaseID()).getValue());
// Role mapping
List<String> roles = AssertionUtil.getRoles(assertion, null);
Assert.assertTrue(roles.contains("example"));
}
// direct-public fails impersonation
{
Response response = exchangeUrl.request().header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader("direct-public", "secret")).post(Entity.form(new Form().param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE).param(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.SAML2_TOKEN_TYPE).param(OAuth2Constants.REQUESTED_SUBJECT, "impersonated-user").param(OAuth2Constants.AUDIENCE, SAML_SIGNED_TARGET)));
Assert.assertEquals(403, response.getStatus());
response.close();
}
// direct-no-secret fails impersonation
{
Response response = exchangeUrl.request().header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader("direct-no-secret", "secret")).post(Entity.form(new Form().param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE).param(OAuth2Constants.REQUESTED_TOKEN_TYPE, OAuth2Constants.SAML2_TOKEN_TYPE).param(OAuth2Constants.REQUESTED_SUBJECT, "impersonated-user").param(OAuth2Constants.AUDIENCE, SAML_SIGNED_TARGET)));
Assert.assertTrue(response.getStatus() >= 400);
response.close();
}
}
use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.
the class ClientTokenExchangeTest method testDirectImpersonation.
@Test
@UncaughtServerErrorExpected
public void testDirectImpersonation() throws Exception {
testingClient.server().run(ClientTokenExchangeTest::setupRealm);
Client httpClient = AdminClientUtil.createResteasyClient();
WebTarget exchangeUrl = httpClient.target(OAuthClient.AUTH_SERVER_ROOT).path("/realms").path(TEST).path("protocol/openid-connect/token");
System.out.println("Exchange url: " + exchangeUrl.getUri().toString());
// direct-exchanger can impersonate from token "user" to user "impersonated-user"
{
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")));
Assert.assertEquals(200, response.getStatus());
AccessTokenResponse accessTokenResponse = response.readEntity(AccessTokenResponse.class);
response.close();
String exchangedTokenString = accessTokenResponse.getToken();
TokenVerifier<AccessToken> verifier = TokenVerifier.create(exchangedTokenString, AccessToken.class);
AccessToken exchangedToken = verifier.parse().getToken();
Assert.assertEquals("direct-exchanger", exchangedToken.getIssuedFor());
Assert.assertNull(exchangedToken.getAudience());
Assert.assertEquals(exchangedToken.getPreferredUsername(), "impersonated-user");
Assert.assertNull(exchangedToken.getRealmAccess());
}
// direct-legal can impersonate from token "user" to user "impersonated-user" and to "target" client
{
Response response = exchangeUrl.request().header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader("direct-legal", "secret")).post(Entity.form(new Form().param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE).param(OAuth2Constants.REQUESTED_SUBJECT, "impersonated-user").param(OAuth2Constants.AUDIENCE, "target")));
Assert.assertEquals(200, response.getStatus());
AccessTokenResponse accessTokenResponse = response.readEntity(AccessTokenResponse.class);
response.close();
String exchangedTokenString = accessTokenResponse.getToken();
TokenVerifier<AccessToken> verifier = TokenVerifier.create(exchangedTokenString, AccessToken.class);
AccessToken exchangedToken = verifier.parse().getToken();
Assert.assertEquals("direct-legal", exchangedToken.getIssuedFor());
Assert.assertEquals("target", exchangedToken.getAudience()[0]);
Assert.assertEquals(exchangedToken.getPreferredUsername(), "impersonated-user");
Assert.assertTrue(exchangedToken.getRealmAccess().isUserInRole("example"));
}
// direct-public fails impersonation
{
Response response = exchangeUrl.request().header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader("direct-public", "secret")).post(Entity.form(new Form().param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE).param(OAuth2Constants.REQUESTED_SUBJECT, "impersonated-user").param(OAuth2Constants.AUDIENCE, "target")));
Assert.assertEquals(403, response.getStatus());
response.close();
}
// direct-no-secret fails impersonation
{
Response response = exchangeUrl.request().header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader("direct-no-secret", "secret")).post(Entity.form(new Form().param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE).param(OAuth2Constants.REQUESTED_SUBJECT, "impersonated-user").param(OAuth2Constants.AUDIENCE, "target")));
Assert.assertTrue(response.getStatus() >= 400);
response.close();
}
}
use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.
the class BrokerLinkAndTokenExchangeTest method testExternalExchange.
@Test
@UncaughtServerErrorExpected
public void testExternalExchange() throws Exception {
RealmResource childRealm = adminClient.realms().realm(CHILD_IDP);
String accessToken = oauth.doGrantAccessTokenRequest(PARENT_IDP, PARENT2_USERNAME, "password", null, PARENT_CLIENT, "password").getAccessToken();
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
Client httpClient = AdminClientUtil.createResteasyClient();
try {
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();
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).param(OAuth2Constants.SCOPE, OAuth2Constants.SCOPE_OPENID)));
Assert.assertEquals(200, response.getStatus());
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
String idToken = tokenResponse.getIdToken();
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
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, tokenResponse.getToken()).param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE).param(OAuth2Constants.REQUESTED_ISSUER, PARENT_IDP)));
Assert.assertEquals(200, response.getStatus());
tokenResponse = response.readEntity(AccessTokenResponse.class);
Assert.assertEquals(accessToken, tokenResponse.getToken());
response.close();
Assert.assertEquals(1, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
// test logout
response = childLogoutWebTarget(httpClient).queryParam("id_token_hint", idToken).request().get();
response.close();
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
List<FederatedIdentityRepresentation> links = childRealm.users().get(exchangedUserId).getFederatedIdentity();
Assert.assertEquals(1, links.size());
}
{
// check that we can request an exchange again and that the previously linked user is obtained
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).param(OAuth2Constants.SCOPE, OAuth2Constants.SCOPE_OPENID)));
Assert.assertEquals(200, response.getStatus());
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
String idToken = tokenResponse.getIdToken();
JWSInput jws = new JWSInput(tokenResponse.getToken());
AccessToken token = jws.readJsonContent(AccessToken.class);
response.close();
String exchanged2UserId = token.getSubject();
String exchanged2Username = token.getPreferredUsername();
// assert that we get the same linked account as was previously imported
Assert.assertEquals(exchangedUserId, exchanged2UserId);
Assert.assertEquals(exchangedUsername, exchanged2Username);
// test logout
response = childLogoutWebTarget(httpClient).queryParam("id_token_hint", idToken).request().get();
response.close();
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
List<FederatedIdentityRepresentation> links = childRealm.users().get(exchangedUserId).getFederatedIdentity();
Assert.assertEquals(1, links.size());
}
{
// check that we can exchange without specifying an SUBJECT_ISSUER
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.SCOPE, OAuth2Constants.SCOPE_OPENID)));
Assert.assertEquals(200, response.getStatus());
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
String idToken = tokenResponse.getIdToken();
JWSInput jws = new JWSInput(tokenResponse.getToken());
AccessToken token = jws.readJsonContent(AccessToken.class);
response.close();
String exchanged2UserId = token.getSubject();
String exchanged2Username = token.getPreferredUsername();
// assert that we get the same linked account as was previously imported
Assert.assertEquals(exchangedUserId, exchanged2UserId);
Assert.assertEquals(exchangedUsername, exchanged2Username);
// test logout
response = childLogoutWebTarget(httpClient).queryParam("id_token_hint", idToken).request().get();
response.close();
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
List<FederatedIdentityRepresentation> links = childRealm.users().get(exchangedUserId).getFederatedIdentity();
Assert.assertEquals(1, links.size());
}
// cleanup remove the user
childRealm.users().get(exchangedUserId).remove();
{
// test unauthorized client gets 403
Response response = exchangeUrl.request().header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(UNAUTHORIZED_CHILD_CLIENT, "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(403, response.getStatus());
}
} finally {
httpClient.close();
}
}
use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.
the class BrokerLinkAndTokenExchangeTest method checkFeature.
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 = AdminClientUtil.createResteasyClient();
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).param(OAuth2Constants.SCOPE, OAuth2Constants.SCOPE_OPENID)));
Assert.assertEquals(statusCode, response.getStatus());
if (statusCode != Response.Status.NOT_IMPLEMENTED.getStatusCode()) {
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
String idToken = tokenResponse.getIdToken();
Assert.assertNotNull(idToken);
response.close();
Assert.assertEquals(1, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
// test logout
response = childLogoutWebTarget(httpClient).queryParam("id_token_hint", idToken).request().get();
response.close();
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
}
}
} finally {
httpClient.close();
}
}
use of org.keycloak.representations.AccessTokenResponse in project keycloak by keycloak.
the class DemoServletsAdapterTest method testRestCallWithAccessTokenAsQueryParameter.
// KEYCLOAK-1733
@Test
public void testRestCallWithAccessTokenAsQueryParameter() throws Exception {
Client client = createResteasyClient(true, true);
try {
WebTarget webTarget = client.target(testRealmPage.toString() + "/protocol/openid-connect/token");
Form form = new Form();
form.param("grant_type", "password");
form.param("client_id", "customer-portal-public");
form.param("username", "bburke@redhat.com");
form.param("password", "password");
Response response = webTarget.request().post(Entity.form(form));
Assert.assertEquals(200, response.getStatus());
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
response.close();
String accessToken = tokenResponse.getToken();
// test without token
response = client.target(customerDb.getInjectedUrl().toString()).request().get();
Assert.assertEquals(401, response.getStatus());
response.close();
// test with access_token as QueryParamter
response = client.target(customerDb.getInjectedUrl().toString()).queryParam("access_token", accessToken).request().get();
Assert.assertEquals(200, response.getStatus());
response.close();
} finally {
client.close();
}
}
Aggregations