diff --git a/src/main/java/org/gcube/common/authorization/utils/secret/JWTSecret.java b/src/main/java/org/gcube/common/authorization/utils/secret/JWTSecret.java index 2dfe86d..e3c1836 100644 --- a/src/main/java/org/gcube/common/authorization/utils/secret/JWTSecret.java +++ b/src/main/java/org/gcube/common/authorization/utils/secret/JWTSecret.java @@ -1,12 +1,15 @@ package org.gcube.common.authorization.utils.secret; import java.net.URLDecoder; +import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Base64; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; @@ -19,6 +22,7 @@ import org.gcube.common.authorization.utils.user.KeycloakUser; import org.gcube.common.authorization.utils.user.User; import org.gcube.common.keycloak.KeycloakClientFactory; import org.gcube.common.keycloak.model.AccessToken; +import org.gcube.common.keycloak.model.AccessToken.Access; import org.gcube.common.keycloak.model.ModelUtils; import org.gcube.common.keycloak.model.RefreshToken; import org.gcube.common.keycloak.model.TokenResponse; @@ -44,6 +48,10 @@ public class JWTSecret extends Secret { protected AccessToken accessToken; protected TokenResponse tokenResponse; protected RenewalProvider renewalProvider; + protected Set roles; + protected ClientInfo clientInfo; + protected Caller caller; + protected String context; public JWTSecret(String token) { super(10, token); @@ -105,37 +113,58 @@ public class JWTSecret extends Secret { } return accessToken; } + + protected Set getRoles() throws Exception{ + if(roles == null) { + Map accesses = getAccessToken().getResourceAccess(); + String context = getContext(); + Access access = accesses.get(URLEncoder.encode(context, StandardCharsets.UTF_8.toString())); + if(access != null) { + roles = access.getRoles(); + }else { + roles = new HashSet<>(); + } + } + return roles; + } @Override public ClientInfo getClientInfo() throws Exception { - getAccessToken(); - List roles = new ArrayList<>(accessToken.getRealmAccess().getRoles()); - ClientInfo clientInfo = new UserInfo(accessToken.getPreferredUsername(), roles, accessToken.getEmail(), accessToken.getGivenName(), accessToken.getFamilyName()); + if(clientInfo==null) { + getAccessToken(); + List roles = new ArrayList<>(getRoles()); + clientInfo = new UserInfo(accessToken.getPreferredUsername(), roles, accessToken.getEmail(), accessToken.getGivenName(), accessToken.getFamilyName()); + } return clientInfo; } @Override public Caller getCaller() throws Exception { - Caller caller = new Caller(getClientInfo(), "token"); + if(caller==null) { + caller = new Caller(getClientInfo(), "token"); + } return caller; } @Override public String getContext() throws Exception { - String context = null; - String[] audience = getAccessToken().getAudience(); - for (String aud : audience) { - if (aud != null && aud.compareTo("") != 0) { - try { - context = URLDecoder.decode(context, StandardCharsets.UTF_8.toString()); - ScopeBean scopeBean = new ScopeBean(context); - return scopeBean.toString(); - } catch (Exception e) { - logger.error("Invalid context name for audience {} in access token. Trying next one if any.", aud, e); + if(context==null) { + String[] audience = getAccessToken().getAudience(); + for (String aud : audience) { + if (aud != null && aud.compareTo("") != 0) { + try { + String contextToBeValidated = URLDecoder.decode(aud, StandardCharsets.UTF_8.toString()); + ScopeBean scopeBean = new ScopeBean(contextToBeValidated); + context = scopeBean.toString(); + return context; + } catch (Exception e) { + logger.error("Invalid context name for audience {} in access token. Trying next one if any.", aud, e); + } } } + throw new Exception("Invalid context in access token"); } - throw new Exception("Invalid context in access token"); + return context; } @Override @@ -187,6 +216,7 @@ public class JWTSecret extends Secret { ObjectMapper objectMapper = new ObjectMapper(); String accessTokenString = objectMapper.writeValueAsString(accessToken); user = objectMapper.readValue(accessTokenString, KeycloakUser.class); + user.setRoles(getRoles()); } catch (Exception e) { throw new RuntimeException(); }