diff --git a/src/main/java/org/gcube/common/security/secrets/AccessTokenSecret.java b/src/main/java/org/gcube/common/security/secrets/AccessTokenSecret.java index ec25487..37da489 100644 --- a/src/main/java/org/gcube/common/security/secrets/AccessTokenSecret.java +++ b/src/main/java/org/gcube/common/security/secrets/AccessTokenSecret.java @@ -1,88 +1,84 @@ package org.gcube.common.security.secrets; -import java.util.Base64; -import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; -import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; -import org.gcube.common.keycloak.model.AccessToken; +import org.gcube.common.keycloak.KeycloakClient; +import org.gcube.common.keycloak.KeycloakClientFactory; +import org.gcube.common.keycloak.model.TokenResponse; import org.gcube.common.security.Owner; +/** + * @author Luca Frosini (ISTI - CNR) + */ public class AccessTokenSecret extends Secret { - private static final String AUTH_HEADER = "Authorization"; - private static final String USER_HEADER = "d4s-user"; + //private static final Logger logger = LoggerFactory.getLogger(JWTSecret.class); + + /** + * The interval of time expressed in milliseconds used as guard to refresh the token before that it expires . + * TimeUnit has been used to in place of just + * using the number to have a clearer code + */ + public static final long TOLERANCE = TimeUnit.MILLISECONDS.toMillis(200); + + private String accessToken; - private String encodedAccessToken; - private Owner owner; private String context; + private UmaTokenSecret umaTokenSecret; - private AccessToken accessToken; + protected boolean initialised = false; - private boolean initialised = false; + public AccessTokenSecret(String accessToken, String context) { + this.accessToken = accessToken; + this.context = context; + init(); + } - public AccessTokenSecret(String encodedAccessToken) { - this.encodedAccessToken = encodedAccessToken; + private synchronized void init() { + try { + KeycloakClient client = KeycloakClientFactory.newInstance(); + TokenResponse tokenResponse = client.queryUMAToken(context, "Bearer "+accessToken, context, null); + this.umaTokenSecret = new UmaTokenSecret(tokenResponse.getAccessToken()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + private synchronized void refreshAccessToken() { + try { + KeycloakClient client = KeycloakClientFactory.newInstance(); + TokenResponse tokenResponse = client.queryUMAToken(context, "Bearer "+accessToken, context, null); + this.umaTokenSecret = new UmaTokenSecret(tokenResponse.getAccessToken()); + } catch (Exception e) { + throw new RuntimeException(e); + } } @Override public Owner getOwner() { - init(); - return this.owner; + return this.umaTokenSecret.getOwner(); } @Override public String getContext() { - init(); - return this.context; + if (this.umaTokenSecret.isExpired()) + refreshAccessToken(); + return this.umaTokenSecret.getContext(); } @Override public Map getHTTPAuthorizationHeaders() { - Map authorizationHeaders = new HashMap<>(); - authorizationHeaders.put(AUTH_HEADER, "Bearer " + this.encodedAccessToken); - String encodedUser = Base64.getEncoder().encodeToString(this.getOwner().getId().getBytes()); - authorizationHeaders.put(USER_HEADER, encodedUser); - return authorizationHeaders; - + if (this.umaTokenSecret.isExpired()) + refreshAccessToken(); + return this.umaTokenSecret.getHTTPAuthorizationHeaders(); } - protected String getEncodedAccessToken() { - return encodedAccessToken; - } - - @Override public boolean isExpired() { - init(); - return accessToken.isExpired(); + return false; } - private synchronized void init() { - if (!initialised) - try { - String realAccessTokenEncoded = encodedAccessToken.split("\\.")[1]; - - String decodedAccessPart = new String(Base64.getDecoder().decode(realAccessTokenEncoded.getBytes())); - - ObjectMapper objectMapper = new ObjectMapper(); - GCubeJWTObject obj = objectMapper.readValue(decodedAccessPart, GCubeJWTObject.class); - owner = new Owner(obj.getUsername(), obj.getRoles(), obj.getEmail(), obj.getFirstName(), obj.getLastName(), obj.isExternalService()); - owner.setClientName(obj.getClientName()); - owner.setContactOrganisation(obj.getContactOrganisation()); - owner.setClientName(obj.getClientName()); - context = obj.getContext(); - - this.accessToken = objectMapper.readValue(decodedAccessPart, AccessToken.class); - - initialised = true; - } catch (Exception e) { - throw new RuntimeException(e); - } - - } - -} +} \ No newline at end of file diff --git a/src/main/java/org/gcube/common/security/secrets/CredentialSecret.java b/src/main/java/org/gcube/common/security/secrets/CredentialSecret.java index b430e81..5c17835 100644 --- a/src/main/java/org/gcube/common/security/secrets/CredentialSecret.java +++ b/src/main/java/org/gcube/common/security/secrets/CredentialSecret.java @@ -14,7 +14,7 @@ public class CredentialSecret extends Secret { private String username; private String password; private String context; - private AccessTokenSecret accessTokenSecret; + private UmaTokenSecret accessTokenSecret; public CredentialSecret(String username, String password, String context) { @@ -32,7 +32,7 @@ public class CredentialSecret extends Secret { try { KeycloakClient client = KeycloakClientFactory.newInstance(); TokenResponse response = client.queryUMAToken(context, username, password, context, null); - this.accessTokenSecret = new AccessTokenSecret(response.getAccessToken()); + this.accessTokenSecret = new UmaTokenSecret(response.getAccessToken()); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/src/main/java/org/gcube/common/security/secrets/JWTSecret.java b/src/main/java/org/gcube/common/security/secrets/JWTSecret.java deleted file mode 100644 index de3782d..0000000 --- a/src/main/java/org/gcube/common/security/secrets/JWTSecret.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.gcube.common.security.secrets; - -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import org.gcube.common.keycloak.KeycloakClient; -import org.gcube.common.keycloak.KeycloakClientFactory; -import org.gcube.common.keycloak.model.TokenResponse; -import org.gcube.common.security.Owner; - -/** - * @author Luca Frosini (ISTI - CNR) - */ -public class JWTSecret extends Secret { - - //private static final Logger logger = LoggerFactory.getLogger(JWTSecret.class); - - /** - * The interval of time expressed in milliseconds used as guard to refresh the token before that it expires . - * TimeUnit has been used to in place of just - * using the number to have a clearer code - */ - public static final long TOLERANCE = TimeUnit.MILLISECONDS.toMillis(200); - - private String jwtToken; - - - private String context; - private AccessTokenSecret accessTokenSecret; - - protected boolean initialised = false; - - public JWTSecret(String jwtToken) { - this.jwtToken = jwtToken; - init(); - } - - private synchronized void init() { - try { - KeycloakClient client = KeycloakClientFactory.newInstance(); - TokenResponse tokenResponse = client.queryUMAToken(context, "Bearer "+jwtToken, context, null); - this.accessTokenSecret = new AccessTokenSecret(tokenResponse.getAccessToken()); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private synchronized void refreshAccessToken() { - try { - KeycloakClient client = KeycloakClientFactory.newInstance(); - TokenResponse tokenResponse = client.queryUMAToken(context, "Bearer "+jwtToken, context, null); - this.accessTokenSecret = new AccessTokenSecret(tokenResponse.getAccessToken()); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - public Owner getOwner() { - return this.accessTokenSecret.getOwner(); - } - - @Override - public String getContext() { - if (this.accessTokenSecret.isExpired()) - refreshAccessToken(); - return this.accessTokenSecret.getContext(); - } - - @Override - public Map getHTTPAuthorizationHeaders() { - if (this.accessTokenSecret.isExpired()) - refreshAccessToken(); - return this.accessTokenSecret.getHTTPAuthorizationHeaders(); - } - - @Override - public boolean isExpired() { - return false; - } - - -} \ No newline at end of file diff --git a/src/main/java/org/gcube/common/security/secrets/UmaTokenSecret.java b/src/main/java/org/gcube/common/security/secrets/UmaTokenSecret.java new file mode 100644 index 0000000..bba3625 --- /dev/null +++ b/src/main/java/org/gcube/common/security/secrets/UmaTokenSecret.java @@ -0,0 +1,87 @@ +package org.gcube.common.security.secrets; + +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; + +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.common.keycloak.model.AccessToken; +import org.gcube.common.security.Owner; + +public class UmaTokenSecret extends Secret { + + private static final String AUTH_HEADER = "Authorization"; + private static final String USER_HEADER = "d4s-user"; + + private String encodedUmaToken; + + private Owner owner; + private String context; + + private AccessToken accessToken; + + private boolean initialised = false; + + public UmaTokenSecret(String encodedUmaToken) { + this.encodedUmaToken = encodedUmaToken; + } + + @Override + public Owner getOwner() { + init(); + return this.owner; + } + + @Override + public String getContext() { + init(); + return this.context; + } + + @Override + public Map getHTTPAuthorizationHeaders() { + Map authorizationHeaders = new HashMap<>(); + authorizationHeaders.put(AUTH_HEADER, "Bearer " + this.encodedUmaToken); + String encodedUser = Base64.getEncoder().encodeToString(this.getOwner().getId().getBytes()); + authorizationHeaders.put(USER_HEADER, encodedUser); + return authorizationHeaders; + + } + + protected String getEncodedUmaToken() { + return encodedUmaToken; + } + + + @Override + public boolean isExpired() { + init(); + return accessToken.isExpired(); + } + + private synchronized void init() { + if (!initialised) + try { + + String realAccessTokenEncoded = encodedUmaToken.split("\\.")[1]; + + String decodedAccessPart = new String(Base64.getDecoder().decode(realAccessTokenEncoded.getBytes())); + + ObjectMapper objectMapper = new ObjectMapper(); + GCubeJWTObject obj = objectMapper.readValue(decodedAccessPart, GCubeJWTObject.class); + owner = new Owner(obj.getUsername(), obj.getRoles(), obj.getEmail(), obj.getFirstName(), obj.getLastName(), obj.isExternalService()); + owner.setClientName(obj.getClientName()); + owner.setContactOrganisation(obj.getContactOrganisation()); + owner.setClientName(obj.getClientName()); + context = obj.getContext(); + + this.accessToken = objectMapper.readValue(decodedAccessPart, AccessToken.class); + + initialised = true; + } catch (Exception e) { + throw new RuntimeException(e); + } + + } + +} diff --git a/src/test/java/org/gcube/common/security/secrets/TestSecrets.java b/src/test/java/org/gcube/common/security/secrets/TestSecrets.java new file mode 100644 index 0000000..c55bf2c --- /dev/null +++ b/src/test/java/org/gcube/common/security/secrets/TestSecrets.java @@ -0,0 +1,14 @@ +package org.gcube.common.security.secrets; + +public class TestSecrets { +/* + public void test(){ + new JWTSecret(jwtToken): + new UmaTokenSecret(encodedAccessToken); + new CredentialSecret(username, password, context); + new GCubeSecret(gcubeToken); + + SecretManagerProvider.instance.set(secret); + } +*/ +}