From cec6726b909ab1c769fee9eac251016777427af4 Mon Sep 17 00:00:00 2001 From: lucio Date: Tue, 26 Jul 2022 15:11:22 +0200 Subject: [PATCH] removed removal provider that for now is not needed --- .gitignore | 1 + .../security/renewal/ClientIDManager.java | 52 ------- .../security/renewal/RenewalProvider.java | 11 -- .../security/secrets/AccessTokenSecret.java | 12 +- .../security/secrets/CredentialSecret.java | 8 +- .../common/security/secrets/GCubeSecret.java | 5 - .../common/security/secrets/JWTSecret.java | 142 ++++-------------- 7 files changed, 39 insertions(+), 192 deletions(-) delete mode 100644 src/main/java/org/gcube/common/security/renewal/ClientIDManager.java delete mode 100644 src/main/java/org/gcube/common/security/renewal/RenewalProvider.java diff --git a/.gitignore b/.gitignore index 0f44a0f..4110018 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target/ /.classpath +/bin/ diff --git a/src/main/java/org/gcube/common/security/renewal/ClientIDManager.java b/src/main/java/org/gcube/common/security/renewal/ClientIDManager.java deleted file mode 100644 index 41490bd..0000000 --- a/src/main/java/org/gcube/common/security/renewal/ClientIDManager.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.gcube.common.security.renewal; - -import java.net.URL; - -import org.gcube.common.keycloak.KeycloakClientFactory; -import org.gcube.common.keycloak.model.TokenResponse; -import org.gcube.common.security.secrets.JWTSecret; -import org.gcube.common.security.secrets.Secret; - -/** - * @author Luca Frosini (ISTI - CNR) - */ -public class ClientIDManager implements RenewalProvider { - - protected final String clientID; - protected final String clientSecret; - protected final URL endpoint; - - public ClientIDManager(String clientID, String clientSecret, URL endpoint) { - this.clientID = clientID; - this.clientSecret = clientSecret; - this.endpoint = endpoint; - } - - public Secret getSecret() throws Exception { - TokenResponse tokenResponse = KeycloakClientFactory.newInstance().queryUMAToken(endpoint, clientID, clientSecret, null); - - JWTSecret jwtSecret = new JWTSecret(tokenResponse.getAccessToken()); - jwtSecret.setRenewalProvider(this); - - jwtSecret.setTokenResponse(tokenResponse); - - return jwtSecret; - } - - public Secret getSecret(String context) throws Exception { - TokenResponse tokenResponse = KeycloakClientFactory.newInstance().queryUMAToken(endpoint, clientID, clientSecret, context, null); - - JWTSecret jwtSecret = new JWTSecret(tokenResponse.getAccessToken()); - jwtSecret.setRenewalProvider(this); - - jwtSecret.setTokenResponse(tokenResponse); - - return jwtSecret; - } - - @Override - public Secret renew() throws Exception { - return getSecret(); - } - -} diff --git a/src/main/java/org/gcube/common/security/renewal/RenewalProvider.java b/src/main/java/org/gcube/common/security/renewal/RenewalProvider.java deleted file mode 100644 index e182dfa..0000000 --- a/src/main/java/org/gcube/common/security/renewal/RenewalProvider.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.gcube.common.security.renewal; - -import org.gcube.common.security.secrets.Secret; - -/** - * @author Luca Frosini (ISTI - CNR) - */ -public interface RenewalProvider { - - public Secret renew() throws Exception; -} 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 a22e0c4..d75cfce 100644 --- a/src/main/java/org/gcube/common/security/secrets/AccessTokenSecret.java +++ b/src/main/java/org/gcube/common/security/secrets/AccessTokenSecret.java @@ -10,6 +10,9 @@ import org.gcube.common.security.Owner; public class AccessTokenSecret extends Secret { + private static final String AUTH_HEADER = "Authorization"; + private static final String USER_HEADER = "d4s-user"; + private String encodedAccessToken; private Owner owner; @@ -39,7 +42,9 @@ public class AccessTokenSecret extends Secret { @Override public Map getHTTPAuthorizationHeaders() { Map authorizationHeaders = new HashMap<>(); - authorizationHeaders.put("Authorization", "Bearer " + this.encodedAccessToken); + authorizationHeaders.put(AUTH_HEADER, "Bearer " + this.encodedAccessToken); + String encodedUser = new String(Base64.getEncoder().encode(this.getOwner().getId().getBytes())); + authorizationHeaders.put(USER_HEADER, encodedUser); return authorizationHeaders; } @@ -55,11 +60,6 @@ public class AccessTokenSecret extends Secret { return accessToken.isExpired(); } - @Override - public boolean isRefreshable() { - return false; - } - private synchronized void init() { if (!initialised) try { 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 8903155..a5a3512 100644 --- a/src/main/java/org/gcube/common/security/secrets/CredentialSecret.java +++ b/src/main/java/org/gcube/common/security/secrets/CredentialSecret.java @@ -31,7 +31,7 @@ public class CredentialSecret extends Secret { private void refreshAccessToken() { try { KeycloakClient client = KeycloakClientFactory.newInstance(); - TokenResponse response = client.queryUMAToken(username, password, context, null); + TokenResponse response = client.queryUMAToken(context, username, password, context, null); this.accessTokenSecret = new AccessTokenSecret(response.getAccessToken()); } catch (Exception e) { throw new RuntimeException(e); @@ -61,11 +61,5 @@ public class CredentialSecret extends Secret { public boolean isExpired() { return false; } - - - @Override - public boolean isRefreshable() { - return false; - } } diff --git a/src/main/java/org/gcube/common/security/secrets/GCubeSecret.java b/src/main/java/org/gcube/common/security/secrets/GCubeSecret.java index ca5e68c..02c3b3f 100644 --- a/src/main/java/org/gcube/common/security/secrets/GCubeSecret.java +++ b/src/main/java/org/gcube/common/security/secrets/GCubeSecret.java @@ -72,9 +72,4 @@ public class GCubeSecret extends Secret { return false; } - @Override - public boolean isRefreshable() { - return false; - } - } diff --git a/src/main/java/org/gcube/common/security/secrets/JWTSecret.java b/src/main/java/org/gcube/common/security/secrets/JWTSecret.java index a95e75b..24ffd54 100644 --- a/src/main/java/org/gcube/common/security/secrets/JWTSecret.java +++ b/src/main/java/org/gcube/common/security/secrets/JWTSecret.java @@ -1,27 +1,19 @@ 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.model.ModelUtils; -import org.gcube.common.keycloak.model.RefreshToken; +import org.gcube.common.keycloak.KeycloakClient; +import org.gcube.common.keycloak.KeycloakClientFactory; import org.gcube.common.keycloak.model.TokenResponse; -import org.gcube.common.keycloak.model.util.Time; import org.gcube.common.security.Owner; -import org.gcube.common.security.renewal.RenewalProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * @author Luca Frosini (ISTI - CNR) */ public class JWTSecret extends Secret { - private static final Logger logger = LoggerFactory.getLogger(JWTSecret.class); + //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 . @@ -30,132 +22,60 @@ public class JWTSecret extends Secret { */ public static final long TOLERANCE = TimeUnit.MILLISECONDS.toMillis(200); - protected String jwtToken; + private String jwtToken; - protected AccessToken accessToken; - protected TokenResponse tokenResponse; - protected RenewalProvider renewalProvider; - protected Owner owner; - protected String context; + + private String context; + private AccessTokenSecret accessTokenSecret; protected boolean initialised = false; public JWTSecret(String jwtToken) { this.jwtToken = jwtToken; - } - - private String getTokenString() { - try { - boolean expired = false; - getAccessToken(); - - if(Time.currentTimeMillis()>=(accessToken.getExp()-TOLERANCE)) { - expired = true; - if(tokenResponse!=null) { - try { - //KeycloakClientFactory.newInstance().refreshToken(URL, this.getOwner().getId(), tokenResponse); - expired = false; - }catch (Exception e) { - logger.warn("Unable to refresh the token with RefreshToken. Going to try to renew it if possible.", e); - } - } - } - - if(expired && renewalProvider!=null) { - try { - JWTSecret renewed = (JWTSecret) renewalProvider.renew(); - this.jwtToken = renewed.jwtToken; - this.accessToken = getAccessToken(); - }catch (Exception e) { - logger.warn("Unable to renew the token with the RenewalProvider. I'll continue using the old token.", e); - } - } - }catch (Exception e) { - logger.error("Unexpected error in the procedure to evaluate/refresh the current token. I'll continue using the old token.", e); - } - return jwtToken; - } - - - protected AccessToken getAccessToken() { - if(accessToken==null) { - String realUmaTokenEncoded = jwtToken.split("\\.")[1]; - String realUmaToken = new String(Base64.getDecoder().decode(realUmaTokenEncoded.getBytes())); - ObjectMapper mapper = new ObjectMapper(); - try { - accessToken = mapper.readValue(realUmaToken, AccessToken.class); - }catch(Exception e){ - logger.error("Error parsing JWT token",e); - throw new RuntimeException("Error parsing JWT token", e); - } - } - return accessToken; + init(); } private synchronized void init() { - if (!initialised) - try { - ObjectMapper objectMapper = new ObjectMapper(); - String accessTokenString = objectMapper.writeValueAsString(getAccessToken()); - GCubeJWTObject obj = objectMapper.readValue(accessTokenString, GCubeJWTObject.class); - Owner 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(); - initialised = true; - } catch (Exception e) { - throw new RuntimeException(); - } + 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() { - init(); - return this.owner; + return this.accessTokenSecret.getOwner(); } @Override public String getContext() { - init(); - return this.context; + if (this.accessTokenSecret.isExpired()) + refreshAccessToken(); + return this.accessTokenSecret.getContext(); } @Override public Map getHTTPAuthorizationHeaders() { - Map authorizationHeaders = new HashMap<>(); - authorizationHeaders.put("Authorization", "Bearer " + getTokenString()); - return authorizationHeaders; - } - - public void setRenewalProvider(RenewalProvider renewalProvider) { - this.renewalProvider = renewalProvider; - } - - public void setTokenResponse(TokenResponse tokenResponse) { - this.tokenResponse = tokenResponse; - } - - protected boolean isExpired(AccessToken accessToken) { - return Time.currentTimeMillis()>accessToken.getExp(); + if (this.accessTokenSecret.isExpired()) + refreshAccessToken(); + return this.accessTokenSecret.getHTTPAuthorizationHeaders(); } @Override public boolean isExpired() { - return isExpired(getAccessToken()); - } - - @Override - public boolean isRefreshable() { - if(tokenResponse!=null) { - try { - RefreshToken refreshToken = ModelUtils.getRefreshTokenFrom(tokenResponse); - return isExpired(refreshToken); - } catch (Exception e) { - return false; - } - } return false; }