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 * * @author Mauro Mugnaini * */ public class D4ScienceIAMClient { private KeycloakClient keycloakClient; 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 { try { return getKeycloakClient().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); } private D4ScienceIAMClientAutentication(D4ScienceIAMClient client, URL tokenURL, String clientId, String clientSecret) throws D4ScienceIAMClientException { this.tokenURL = tokenURL; try { this.tokenResponse = getKeycloakClient().queryOIDCToken(tokenURL, clientId, clientSecret); } catch (KeycloakClientException e) { throw new D4ScienceIAMClientException(e); } } private TokenResponse getAuthenticationTokenResponse() { return tokenResponse; } public String getAccessToken() { return getAuthenticationTokenResponse().getAccessToken(); } public boolean isExpired() throws D4ScienceIAMClientException { try { return ModelUtils.getAccessTokenFrom(getAuthenticationTokenResponse()).isExpired(); } catch (Exception e) { throw new D4ScienceIAMClientException(e); } } public boolean canBeRefreshed() throws D4ScienceIAMClientException { try { RefreshToken refreshToken = ModelUtils.getRefreshTokenFrom(getAuthenticationTokenResponse()); return refreshToken != null && !refreshToken.isExpired(); } catch (Exception e) { throw new D4ScienceIAMClientException(e); } } public void refreshAuthentication() throws D4ScienceIAMClientException { try { this.tokenResponse = getKeycloakClient().refreshToken(tokenURL, getAuthenticationTokenResponse()); } catch (KeycloakClientException e) { throw new D4ScienceIAMClientException(e); } } public D4ScienceIAMClientAuthorization authorize(String audience, List permissions) throws D4ScienceIAMClientException { return new D4ScienceIAMClientAuthorization(audience, permissions); } public class D4ScienceIAMClientAuthorization { TokenResponse tokenResponse; private D4ScienceIAMClientAuthorization(String audience, List 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 getRoles() throws D4ScienceIAMClientException { AccessToken accessToken; try { accessToken = ModelUtils.getAccessTokenFrom(getAuthorizationTokenResponse()); } catch (Exception e) { throw new D4ScienceIAMClientException(e); } Set allRoles = new HashSet<>(accessToken.getRealmAccess().getRoles()); accessToken.getResourceAccess().forEach((r, a) -> allRoles.addAll(a.getRoles())); return allRoles; } public Set getResourceRoles(String resource) throws D4ScienceIAMClientException { AccessToken accessToken; try { accessToken = ModelUtils.getAccessTokenFrom(getAuthorizationTokenResponse()); } catch (Exception e) { throw new D4ScienceIAMClientException(e); } Set resourceRoles = new HashSet<>(accessToken.getResourceAccess().get(resource).getRoles()); return resourceRoles; } public Set getAudienceResourceRoles() throws D4ScienceIAMClientException { AccessToken accessToken; try { accessToken = ModelUtils.getAccessTokenFrom(getAuthorizationTokenResponse()); } catch (Exception e) { throw new D4ScienceIAMClientException(e); } Set 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); } } } } }