removed removal provider that for now is not needed

This commit is contained in:
Lucio Lelii 2022-07-26 15:11:22 +02:00
parent 7b0a5b96bf
commit cec6726b90
7 changed files with 39 additions and 192 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/target/
/.classpath
/bin/

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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<String, String> getHTTPAuthorizationHeaders() {
Map<String, String> 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 {

View File

@ -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;
}
}

View File

@ -72,9 +72,4 @@ public class GCubeSecret extends Secret {
return false;
}
@Override
public boolean isRefreshable() {
return false;
}
}

View File

@ -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<String, String> getHTTPAuthorizationHeaders() {
Map<String, String> 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;
}