[#24701, #23356] Improved and tested version, ready for trial implementation

This commit is contained in:
Mauro Mugnaini 2023-03-23 18:19:49 +01:00
parent c87aba6ed5
commit 72a502c5de
7 changed files with 448 additions and 201 deletions

View File

@ -0,0 +1,136 @@
package org.gcube.common.iam;
import java.util.HashSet;
import java.util.Set;
import org.gcube.common.keycloak.KeycloakClientException;
import org.gcube.common.keycloak.model.AccessToken;
import org.gcube.common.keycloak.model.ModelUtils;
import org.gcube.common.keycloak.model.RefreshToken;
import org.gcube.common.keycloak.model.TokenResponse;
public class AbstractIAMResponse implements IAMResponse {
private D4ScienceIAMClient iamClient;
private TokenResponse tokenResponse;
public AbstractIAMResponse(D4ScienceIAMClient iamClient, TokenResponse tokenResponse) {
setIamClient(iamClient);
setTokenResponse(tokenResponse);
}
public void setIamClient(D4ScienceIAMClient iamClient) {
this.iamClient = iamClient;
}
public D4ScienceIAMClient getIamClient() {
return iamClient;
}
public void setTokenResponse(TokenResponse tokenResponse) {
this.tokenResponse = tokenResponse;
}
protected TokenResponse getTokenResponse() {
return tokenResponse;
}
@Override
public AccessToken getAccessToken() throws D4ScienceIAMClientException {
try {
return ModelUtils.getAccessTokenFrom(getTokenResponse());
} catch (Exception e) {
throw new D4ScienceIAMClientException(e);
}
}
public String getAccessTokenString() {
return getTokenResponse().getAccessToken();
}
@Override
public boolean isExpired() throws D4ScienceIAMClientException {
try {
return ModelUtils.getAccessTokenFrom(getTokenResponse()).isExpired();
} catch (Exception e) {
throw new D4ScienceIAMClientException(e);
}
}
@Override
public boolean canBeRefreshed() throws D4ScienceIAMClientException {
try {
RefreshToken refreshToken = ModelUtils.getRefreshTokenFrom(getTokenResponse());
return refreshToken != null && !refreshToken.isExpired();
} catch (Exception e) {
throw new D4ScienceIAMClientException(e);
}
}
@Override
public void refresh() throws D4ScienceIAMClientException {
try {
this.tokenResponse = getIamClient().getKeycloakClient().refreshToken(getIamClient().getTokenEndpointURL(),
getTokenResponse());
} catch (KeycloakClientException e) {
throw new D4ScienceIAMClientException(e);
}
}
@Override
public Set<String> getRealmRoles() throws D4ScienceIAMClientException {
AccessToken accessToken = getAccessToken();
return accessToken.getRealmAccess() != null ? accessToken.getRealmAccess().getRoles() : new HashSet<>();
}
@Override
public Set<String> getRoles() throws D4ScienceIAMClientException {
AccessToken accessToken = getAccessToken();
Set<String> roles = getRealmRoles();
accessToken.getResourceAccess().forEach((r, a) -> roles.addAll(a.getRoles()));
return roles;
}
@Override
public Set<String> getResourceRoles(String resource) throws D4ScienceIAMClientException {
AccessToken accessToken = getAccessToken();
return accessToken.getResourceAccess() != null ? (accessToken.getResourceAccess().get(resource) != null
? accessToken.getResourceAccess().get(resource).getRoles()
: new HashSet<>()) : new HashSet<>();
}
@Override
public Set<String> getAudienceResourceRoles() throws D4ScienceIAMClientException {
AccessToken accessToken = getAccessToken();
return accessToken.getResourceAccess() != null
? (accessToken.getResourceAccess().get(accessToken.getAudience()[0]) != null
? accessToken.getResourceAccess().get(accessToken.getAudience()[0]).getRoles()
: new HashSet<>())
: new HashSet<>();
}
@Override
public String getName() throws D4ScienceIAMClientException {
return getAccessToken().getName();
}
@Override
public String getContactPerson() throws D4ScienceIAMClientException {
AccessToken accessToken = getAccessToken();
return (String) (accessToken.getOtherClaims() != null
? accessToken.getOtherClaims()
.get(D4ScienceCustomClaims.CLIENT_CONTACT_PERSON)
: null);
}
@Override
public String getContactOrganization() throws D4ScienceIAMClientException {
AccessToken accessToken = getAccessToken();
return (String) (accessToken.getOtherClaims() != null
? accessToken.getOtherClaims()
.get(D4ScienceCustomClaims.CLIENT_CONTACT_ORGANISATION)
: null);
}
}

View File

@ -15,6 +15,6 @@ public class D4ScienceCustomClaims {
/**
* The registered contact organization of a client with service account
*/
public static final String CLIENT_CONTACT_ORGANIZATION = "contact_person";
public static final String CLIENT_CONTACT_ORGANISATION = "contact_organisation";
}

View File

@ -1,235 +1,118 @@
package org.gcube.common.iam;
import java.net.URL;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.gcube.common.keycloak.KeycloakClient;
import org.gcube.common.keycloak.KeycloakClientException;
import org.gcube.common.keycloak.KeycloakClientFactory;
import org.gcube.common.keycloak.model.AccessToken;
import org.gcube.common.keycloak.model.ModelUtils;
import org.gcube.common.keycloak.model.RefreshToken;
import org.gcube.common.keycloak.model.TokenResponse;
/**
* Helper class that acts as IAM client providing
* Helper class that acts as IAM client providing authentication and authorization using the IAM hiding the underlying implementation
*
* @author Mauro Mugnaini
*
*/
public class D4ScienceIAMClient {
private KeycloakClient keycloakClient;
private URL tokenEndpointURL;
public static D4ScienceIAMClient newInstance() {
return new D4ScienceIAMClient();
}
private D4ScienceIAMClient() {
keycloakClient = KeycloakClientFactory.newInstance();
}
private KeycloakClient getKeycloakClient() {
return keycloakClient;
}
public D4ScienceIAMClientAutentication authenticate(String context, String clientId, String clientSecret)
throws D4ScienceIAMClientException {
return new D4ScienceIAMClientAutentication(this, context, clientId, clientSecret);
}
public D4ScienceIAMClientAutentication authenticate(URL tokenURL, String clientId, String clientSecret)
throws D4ScienceIAMClientException {
return new D4ScienceIAMClientAutentication(this, tokenURL, clientId, clientSecret);
}
public URL getTokenEndpointURL(String context) throws D4ScienceIAMClientException {
/**
* Creates a new client for the specific context, in the default IAM realm.
* @param context the context to be used to obtain the endpoint URL
* @return the client to be used for authn and authz requests
* @throws D4ScienceIAMClientException if an error occurs obtaining the base URL
*/
public static D4ScienceIAMClient newInstance(String context) throws D4ScienceIAMClientException {
KeycloakClient keycloakClient = KeycloakClientFactory.newInstance();
try {
return getKeycloakClient().getRealmBaseURL(context);
return new D4ScienceIAMClient(keycloakClient,
keycloakClient.getTokenEndpointURL(keycloakClient.getRealmBaseURL(context)));
} catch (KeycloakClientException e) {
throw new D4ScienceIAMClientException(e);
}
}
public class D4ScienceIAMClientAutentication {
private URL tokenURL;
private TokenResponse tokenResponse;
private D4ScienceIAMClientAutentication(D4ScienceIAMClient client, String context, String clientId,
String clientSecret) throws D4ScienceIAMClientException {
this(client, client.getTokenEndpointURL(context), clientId, clientSecret);
/**
* Creates a new client for the specific context, in the default realm.
* @param context the context to be used to obtain the endpoint URL
* @param realm the IAM realm
* @return the client to be used for authn and authz requests
* @throws D4ScienceIAMClientException if an error occurs obtaining the base URL
*/
public static D4ScienceIAMClient newInstance(String context, String realm) throws D4ScienceIAMClientException {
KeycloakClient keycloakClient = KeycloakClientFactory.newInstance();
try {
return new D4ScienceIAMClient(keycloakClient,
keycloakClient.getTokenEndpointURL(keycloakClient.getRealmBaseURL(context, realm)));
} catch (KeycloakClientException e) {
throw new D4ScienceIAMClientException(e);
}
}
private D4ScienceIAMClientAutentication(D4ScienceIAMClient client, URL tokenURL, String clientId,
String clientSecret)
throws D4ScienceIAMClientException {
/**
* Creates a new client with the provided endpoint URL.
* @param tokenEndpointURL the endpoint URL
* @return the client to be used for authn and authz requests
*/
public static D4ScienceIAMClient newInstance(URL tokenEndpointURL) {
return new D4ScienceIAMClient(KeycloakClientFactory.newInstance(), tokenEndpointURL);
}
this.tokenURL = tokenURL;
try {
this.tokenResponse = getKeycloakClient().queryOIDCToken(tokenURL, clientId, clientSecret);
} catch (KeycloakClientException e) {
throw new D4ScienceIAMClientException(e);
}
}
private D4ScienceIAMClient(KeycloakClient keycloakClient, URL tokenEndpointURL) {
this.keycloakClient = keycloakClient;
this.tokenEndpointURL = tokenEndpointURL;
}
private TokenResponse getAuthenticationTokenResponse() {
return tokenResponse;
}
protected KeycloakClient getKeycloakClient() {
return this.keycloakClient;
}
public String getAccessToken() {
return getAuthenticationTokenResponse().getAccessToken();
}
public URL getTokenEndpointURL() {
return this.tokenEndpointURL;
}
public boolean isExpired() throws D4ScienceIAMClientException {
try {
return ModelUtils.getAccessTokenFrom(getAuthenticationTokenResponse()).isExpired();
} catch (Exception e) {
throw new D4ScienceIAMClientException(e);
}
}
/**
* Authenticates the client with provided id and secret,
* @param clientId the client id
* @param clientSecret the client secret
* @return the authn object
* @throws D4ScienceIAMClientException if an error occurs during authn process
*/
public D4ScienceIAMClientAuthn authenticate(String clientId, String clientSecret)
throws D4ScienceIAMClientException {
public boolean canBeRefreshed() throws D4ScienceIAMClientException {
try {
RefreshToken refreshToken = ModelUtils.getRefreshTokenFrom(getAuthenticationTokenResponse());
return refreshToken != null && !refreshToken.isExpired();
} catch (Exception e) {
throw new D4ScienceIAMClientException(e);
}
}
return authenticate(clientId, clientSecret, null);
}
public void refreshAuthentication() throws D4ScienceIAMClientException {
try {
this.tokenResponse = getKeycloakClient().refreshToken(tokenURL, getAuthenticationTokenResponse());
} catch (KeycloakClientException e) {
throw new D4ScienceIAMClientException(e);
}
}
/**
* Authenticates the client with provided credentials, reducing the token audience to the requested.
* @param clientId the client id
* @param clientSecret the client secret
* @param audience the requested audience (e.g. a specific context)
* @return the authn object
* @throws D4ScienceIAMClientException if an error occurs during authn process
*/
public D4ScienceIAMClientAuthn authenticate(String clientId, String clientSecret, String audience)
throws D4ScienceIAMClientException {
public D4ScienceIAMClientAuthorization authorize(String audience, List<String> permissions)
throws D4ScienceIAMClientException {
return new D4ScienceIAMClientAuthn(this, clientId, clientSecret, audience);
}
return new D4ScienceIAMClientAuthorization(audience, permissions);
}
public class D4ScienceIAMClientAuthorization {
TokenResponse tokenResponse;
private D4ScienceIAMClientAuthorization(String audience, List<String> permissions)
throws D4ScienceIAMClientException {
try {
this.tokenResponse = getKeycloakClient().queryUMAToken(tokenURL, getAuthenticationTokenResponse(),
audience, permissions);
} catch (KeycloakClientException e) {
throw new D4ScienceIAMClientException(e);
}
}
private TokenResponse getAuthorizationTokenResponse() {
return tokenResponse;
}
public String getAccessToken() {
return getAuthorizationTokenResponse().getAccessToken();
}
public boolean isExpired() throws D4ScienceIAMClientException {
try {
return ModelUtils.getAccessTokenFrom(getAuthorizationTokenResponse()).isExpired();
} catch (Exception e) {
throw new D4ScienceIAMClientException(e);
}
}
public boolean canBeRefreshed() throws D4ScienceIAMClientException {
try {
RefreshToken refreshToken = ModelUtils.getRefreshTokenFrom(getAuthorizationTokenResponse());
return refreshToken != null && !refreshToken.isExpired();
} catch (Exception e) {
throw new D4ScienceIAMClientException(e);
}
}
public void refreshAuthorization() throws D4ScienceIAMClientException {
try {
this.tokenResponse = getKeycloakClient().refreshToken(tokenURL, getAuthorizationTokenResponse());
} catch (KeycloakClientException e) {
throw new D4ScienceIAMClientException(e);
}
}
public Set<String> getRoles() throws D4ScienceIAMClientException {
AccessToken accessToken;
try {
accessToken = ModelUtils.getAccessTokenFrom(getAuthorizationTokenResponse());
} catch (Exception e) {
throw new D4ScienceIAMClientException(e);
}
Set<String> allRoles = new HashSet<>(accessToken.getRealmAccess().getRoles());
accessToken.getResourceAccess().forEach((r, a) -> allRoles.addAll(a.getRoles()));
return allRoles;
}
public Set<String> getResourceRoles(String resource) throws D4ScienceIAMClientException {
AccessToken accessToken;
try {
accessToken = ModelUtils.getAccessTokenFrom(getAuthorizationTokenResponse());
} catch (Exception e) {
throw new D4ScienceIAMClientException(e);
}
Set<String> resourceRoles = new HashSet<>(accessToken.getResourceAccess().get(resource).getRoles());
return resourceRoles;
}
public Set<String> getAudienceResourceRoles() throws D4ScienceIAMClientException {
AccessToken accessToken;
try {
accessToken = ModelUtils.getAccessTokenFrom(getAuthorizationTokenResponse());
} catch (Exception e) {
throw new D4ScienceIAMClientException(e);
}
Set<String> resourceRoles = new HashSet<>(
accessToken.getResourceAccess().get(accessToken.getAudience()[0]).getRoles());
return resourceRoles;
}
public String getName() throws D4ScienceIAMClientException {
try {
return (String) ModelUtils.getAccessTokenFrom(getAuthorizationTokenResponse()).getOtherClaims()
.get(D4ScienceCustomClaims.CLIENT_NAME);
} catch (Exception e) {
throw new D4ScienceIAMClientException(e);
}
}
public String getContactPerson() throws D4ScienceIAMClientException {
try {
return (String) ModelUtils.getAccessTokenFrom(getAuthorizationTokenResponse()).getOtherClaims()
.get(D4ScienceCustomClaims.CLIENT_CONTACT_PERSON);
} catch (Exception e) {
throw new D4ScienceIAMClientException(e);
}
}
public String getContactOrganization() throws D4ScienceIAMClientException {
try {
return (String) ModelUtils.getAccessTokenFrom(getAuthorizationTokenResponse()).getOtherClaims()
.get(D4ScienceCustomClaims.CLIENT_CONTACT_ORGANIZATION);
} catch (Exception e) {
throw new D4ScienceIAMClientException(e);
}
}
}
/**
* Directly authorizes the client by using the provided credentials, for the specific audience and with optional permissions
* @param clientId the client id
* @param clientSecret the client secret
* @param audience the requested audience (e.g. a specific context)
* @param permissions the optional permissions
* @return the authz object
* @throws D4ScienceIAMClientException if an error occurs during authz process
*/
public D4ScienceIAMClientAuthz authorize(String clientId, String clientSecret, String audience,
List<String> permissions)
throws D4ScienceIAMClientException {
return new D4ScienceIAMClientAuthz(this, clientId, clientSecret, audience, permissions);
}
}

View File

@ -0,0 +1,48 @@
package org.gcube.common.iam;
import java.util.List;
import org.gcube.common.keycloak.KeycloakClientException;
import org.gcube.common.keycloak.model.TokenResponse;
public class D4ScienceIAMClientAuthn extends AbstractIAMResponse implements IAMResponse {
protected D4ScienceIAMClientAuthn(D4ScienceIAMClient iamClient, String clientId, String clientSecret)
throws D4ScienceIAMClientException {
this(iamClient, clientId, clientSecret, null);
}
protected D4ScienceIAMClientAuthn(D4ScienceIAMClient iamClient, String clientId, String clientSecret,
String audience)
throws D4ScienceIAMClientException {
super(iamClient, performAuthn(iamClient, clientId, clientSecret, audience));
}
protected static final TokenResponse performAuthn(D4ScienceIAMClient iamClient, String clientId, String clientSecret,
String audience) throws D4ScienceIAMClientException {
try {
return iamClient.getKeycloakClient().queryOIDCTokenWithContext(iamClient.getTokenEndpointURL(), clientId,
clientSecret, audience);
} catch (KeycloakClientException e) {
throw new D4ScienceIAMClientException(e);
}
}
/**
* Authorizes the client by using the authn already obtained, for the specific audience and with optional permissions.
* @param audience the requested audience (e.g. a specific context)
* @param permissions the optional permissions
* @return the authz object
* @throws D4ScienceIAMClientException if an error occurs during authz process
*/
public D4ScienceIAMClientAuthz authorize(String audience, List<String> permissions)
throws D4ScienceIAMClientException {
return new D4ScienceIAMClientAuthz(this, audience, permissions);
}
}

View File

@ -0,0 +1,44 @@
package org.gcube.common.iam;
import java.util.List;
import org.gcube.common.keycloak.KeycloakClientException;
import org.gcube.common.keycloak.model.TokenResponse;
public class D4ScienceIAMClientAuthz extends AbstractIAMResponse implements IAMResponse {
protected D4ScienceIAMClientAuthz(D4ScienceIAMClientAuthn authn, String audience, List<String> permissions)
throws D4ScienceIAMClientException {
super(authn.getIamClient(),
performAuthz(authn.getIamClient(), authn.getTokenResponse(), audience, permissions));
}
private static final TokenResponse performAuthz(D4ScienceIAMClient iamClient, TokenResponse authnTR,
String audience, List<String> permissions) throws D4ScienceIAMClientException {
try {
return iamClient.getKeycloakClient().queryUMAToken(iamClient.getTokenEndpointURL(), authnTR, audience,
permissions);
} catch (KeycloakClientException e) {
throw new D4ScienceIAMClientException(e);
}
}
protected D4ScienceIAMClientAuthz(D4ScienceIAMClient iamClient, String clientId, String clientSecret,
String audience, List<String> permissions) throws D4ScienceIAMClientException {
super(iamClient, performAuthz(iamClient, clientId, clientSecret, audience, permissions));
}
private static final TokenResponse performAuthz(D4ScienceIAMClient iamClient, String clientId, String clientSecret,
String audience, List<String> permissions) throws D4ScienceIAMClientException {
;
try {
return iamClient.getKeycloakClient().queryUMAToken(iamClient.getTokenEndpointURL(), clientId, clientSecret,
audience, permissions);
} catch (KeycloakClientException e) {
throw new D4ScienceIAMClientException(e);
}
}
}

View File

@ -0,0 +1,33 @@
package org.gcube.common.iam;
import java.util.Set;
import org.gcube.common.keycloak.model.AccessToken;
public interface IAMResponse {
public AccessToken getAccessToken() throws D4ScienceIAMClientException;
String getAccessTokenString();
boolean isExpired() throws D4ScienceIAMClientException;
boolean canBeRefreshed() throws D4ScienceIAMClientException;
void refresh() throws D4ScienceIAMClientException;
String getContactOrganization() throws D4ScienceIAMClientException;
String getContactPerson() throws D4ScienceIAMClientException;
String getName() throws D4ScienceIAMClientException;
Set<String> getAudienceResourceRoles() throws D4ScienceIAMClientException;
Set<String> getResourceRoles(String resource) throws D4ScienceIAMClientException;
Set<String> getRoles() throws D4ScienceIAMClientException;
Set<String> getRealmRoles() throws D4ScienceIAMClientException;
}

View File

@ -1,5 +1,14 @@
package org.gcube.common.iam;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.gcube.common.keycloak.model.ModelUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.FixMethodOrder;
@ -13,8 +22,27 @@ public class TestD4ScienceIAMClient {
protected static final Logger logger = LoggerFactory.getLogger(TestD4ScienceIAMClient.class);
protected static final String DEV_ROOT_CONTEXT = "/gcube";
protected static final String CLIENT_ID = "keycloak-client-unit-test";
protected static final String CLIENT_SECRET = "ebf6f82e-9511-408e-8321-203081e472d8";
protected static final String TEST_AUDIENCE = "conductor-server";
protected static final Set<String> REALM_ROLES = Collections.singleton("d4s-client");
protected static final Set<String> CONDUCTOR_SERVER_ROLES = Collections.singleton("dummy-test-role");
protected static final Set<String> OTHER_ROLES = new HashSet<>(Arrays.asList("uma_protection", "Member"));
protected static final String NAME = "Keycloak-client unit-test";
protected static final String CONTACT_PERSON = "mauro.mugnaini";
protected static final String CONTACT_ORGANIZATION = "Nubisware S.r.l.";
protected static Set<String> ALL_ROLES;
@Before
public void setUp() throws Exception {
ALL_ROLES = new HashSet<>();
ALL_ROLES.addAll(REALM_ROLES);
ALL_ROLES.addAll(CONDUCTOR_SERVER_ROLES);
ALL_ROLES.addAll(OTHER_ROLES);
}
@After
@ -22,8 +50,83 @@ public class TestD4ScienceIAMClient {
}
@Test
public void test1() throws Exception {
logger.info("*** [1] ");
public void test1Authn() throws Exception {
logger.info("*** [1] Testing authentication");
D4ScienceIAMClientAuthn authn = D4ScienceIAMClient.newInstance(DEV_ROOT_CONTEXT).authenticate(CLIENT_ID, CLIENT_SECRET);
logger.info("Authn scope: {}", authn.getTokenResponse().getScope());
logger.info("Authn AUDIENCE: {}", (Object[]) authn.getAccessToken().getAudience());
logger.info("Authn RESOURCE ACCESS: {}", authn.getAccessToken().getResourceAccess());
logger.info("Authn ALL roles: {}", authn.getRoles());
logger.info("Authn REALM roles: {}", authn.getRealmRoles());
logger.info("Authn AUDIENCE's roles: {}", authn.getAudienceResourceRoles());
logger.info("Authn D4S identity: '{}' by {} [{}]", authn.getName(), authn.getContactPerson(), authn.getContactOrganization());
logger.info("Authn access token:\n{}", ModelUtils.getAccessTokenPayloadJSONStringFrom(authn.getTokenResponse()));
assertEquals(ALL_ROLES, authn.getRoles());
assertEquals(REALM_ROLES, authn.getRealmRoles());
assertEquals(NAME, authn.getName());
assertEquals(CONTACT_PERSON, authn.getContactPerson());
assertEquals(CONTACT_ORGANIZATION, authn.getContactOrganization());
}
@Test
public void test2AuthnWithSpecificAudience() throws Exception {
logger.info("*** [2] Testing authentication");
D4ScienceIAMClientAuthn authn = D4ScienceIAMClient.newInstance(DEV_ROOT_CONTEXT).authenticate(CLIENT_ID, CLIENT_SECRET, TEST_AUDIENCE);
logger.info("Authn scope: {}", authn.getTokenResponse().getScope());
logger.info("Authn AUDIENCE: {}", (Object[]) authn.getAccessToken().getAudience());
logger.info("Authn RESOURCE ACCESS: {}", authn.getAccessToken().getResourceAccess());
logger.info("Authn ALL roles: {}", authn.getRoles());
logger.info("Authn REALM roles: {}", authn.getRealmRoles());
logger.info("Authn AUDIENCE's roles: {}", authn.getAudienceResourceRoles());
logger.info("Authn D4S identity: '{}' by {} [{}]", authn.getName(), authn.getContactPerson(), authn.getContactOrganization());
logger.info("Authn access token:\n{}", ModelUtils.getAccessTokenPayloadJSONStringFrom(authn.getTokenResponse()));
assertEquals(TEST_AUDIENCE, authn.getAccessToken().getAudience()[0]);
// assertEquals(ALL_ROLES, authn.getRoles()); // This depends on the mapper's "shrink" settings, so it's not safe to let it enabled
assertEquals(CONDUCTOR_SERVER_ROLES, authn.getAudienceResourceRoles());
assertEquals(REALM_ROLES, authn.getRealmRoles());
assertEquals(NAME, authn.getName());
assertEquals(CONTACT_PERSON, authn.getContactPerson());
assertEquals(CONTACT_ORGANIZATION, authn.getContactOrganization());
}
@Test
public void test3AuthnAndAuthz() throws Exception {
logger.info("*** [3] Testing authentication and then authorization");
D4ScienceIAMClientAuthz authz = D4ScienceIAMClient.newInstance(DEV_ROOT_CONTEXT).authenticate(CLIENT_ID, CLIENT_SECRET).authorize(TEST_AUDIENCE, null);
logger.info("Authz scope: {}", authz.getTokenResponse().getScope());
logger.info("Authn AUDIENCE: {}", (Object[]) authz.getAccessToken().getAudience());
logger.info("Authn RESOURCE ACCESS: {}", authz.getAccessToken().getResourceAccess());
logger.info("Authz ALL roles: {}", authz.getRoles());
logger.info("Authz REALM roles: {}", authz.getRealmRoles());
logger.info("Authz AUDIENCE's roles: {}", authz.getAudienceResourceRoles());
logger.info("Authz D4S identity: '{}' by {} [{}]", authz.getName(), authz.getContactPerson(), authz.getContactOrganization());
logger.info("Authz access token:\n{}", ModelUtils.getAccessTokenPayloadJSONStringFrom(authz.getTokenResponse()));
assertEquals(TEST_AUDIENCE, authz.getAccessToken().getAudience()[0]);
assertNotEquals(ALL_ROLES, authz.getRoles());
assertEquals(CONDUCTOR_SERVER_ROLES, authz.getAudienceResourceRoles());
assertEquals(CONDUCTOR_SERVER_ROLES, authz.getRoles());
assertEquals(Collections.emptySet(), authz.getRealmRoles());
}
@Test
public void test4DirectAuthz() throws Exception {
logger.info("*** [4] Testing direct authorization");
D4ScienceIAMClientAuthz authz = D4ScienceIAMClient.newInstance(DEV_ROOT_CONTEXT).authorize(CLIENT_ID, CLIENT_SECRET, TEST_AUDIENCE, null);
logger.info("Authz scope: {}", authz.getTokenResponse().getScope());
logger.info("Authn AUDIENCE: {}", (Object[]) authz.getAccessToken().getAudience());
logger.info("Authn RESOURCE ACCESS: {}", authz.getAccessToken().getResourceAccess());
logger.info("Authz ALL roles: {}", authz.getRoles());
logger.info("Authz REALM roles: {}", authz.getRealmRoles());
logger.info("Authz AUDIENCE's roles: {}", authz.getAudienceResourceRoles());
logger.info("Authz D4S identity: '{}' by {} [{}]", authz.getName(), authz.getContactPerson(), authz.getContactOrganization());
logger.info("Authz access token:\n{}", ModelUtils.getAccessTokenPayloadJSONStringFrom(authz.getTokenResponse()));
assertEquals(TEST_AUDIENCE, authz.getAccessToken().getAudience()[0]);
assertNotEquals(ALL_ROLES, authz.getRoles());
assertEquals(TEST_AUDIENCE, authz.getAccessToken().getAudience()[0]);
assertEquals(CONDUCTOR_SERVER_ROLES, authz.getAudienceResourceRoles());
assertEquals(CONDUCTOR_SERVER_ROLES, authz.getRoles());
assertEquals(Collections.emptySet(), authz.getRealmRoles());
}
}