package org.gcube.oidc.rest; import java.io.Serializable; import java.util.ArrayList; import java.util.Base64; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JWTToken implements Serializable { protected static Logger logger = LoggerFactory.getLogger(JWTToken.class); private static final long serialVersionUID = -7063122428186284827L; public static final String ACCOUNT_RESOURCE = "account"; private String raw; private JSONObject token; private JSONObject payload; public static JWTToken fromString(String tokenString) { if (tokenString == null) { logger.debug("Token string is null, cannot create token object"); return null; } try { return new JWTToken(tokenString); } catch (ParseException e) { logger.error("Cannot parse token string", e); return null; } } private JWTToken(String raw) throws ParseException { this.raw = raw; this.parse(); } private void parse() throws ParseException { token = (JSONObject) new JSONParser().parse(this.raw); String[] parts = getAccessTokenString().split("\\."); payload = (JSONObject) new JSONParser().parse(new String(Base64.getDecoder().decode(parts[1]))); } public String getRaw() { return raw; } public String getAccessTokenString() { return (String) token.get("access_token"); } public String getRefreshTokenString() { return (String) token.get("refresh_token"); } /** * @deprecated Use {@link #getAccessTokenAsBearer()} method instead * @return */ @Deprecated() public String getAsBearer() { return getAccessTokenAsBearer(); } public String getAccessTokenAsBearer() { return "Bearer " + getAccessTokenString(); } public JSONObject getPayload() { return payload; } public String getAzp() { return (String) getPayload().get("azp"); } public Long getExp() { return (Long) getPayload().get("exp"); } public Date getExpAsDate() { return new Date(getExp() * 1000); } public Calendar getExpAsCalendar() { Calendar cal = Calendar.getInstance(); cal.setTime(getExpAsDate()); return cal; } public boolean isExpired() { return new Date().after(getExpAsDate()); } public List getAud() { List audienceStrings = new ArrayList<>(); Object audience = getPayload().get("aud"); if (audience instanceof String) { audienceStrings.add((String) audience); } else if (audience instanceof JSONArray) { JSONArray audienceArray = (JSONArray) audience; for (int i = 0; i < audienceArray.size(); i++) { audienceStrings.add((String) audienceArray.get(i)); } } return audienceStrings; } public String getSub() { return (String) getPayload().get("sub"); } public String getEmail() { return (String) getPayload().get("email"); } public String getFamily() { return (String) getPayload().get("family_name"); } public String getGiven() { return (String) getPayload().get("given_name"); } public String getUserName() { return (String) getPayload().get("preferred_username"); } public String getDisplayName() { return (String) getPayload().get("name"); } protected JSONObject getResourceAccess() { return (JSONObject) getPayload().get("resource_access"); } @SuppressWarnings("unchecked") protected Iterator getResourceAccessKeys() { return getResourceAccess().keySet().iterator(); } public List getResourceAccessRoles(String resource) { JSONArray rolesJsonArray = (JSONArray) ((JSONObject) getResourceAccess().get(resource)) .get("roles"); List roles = new ArrayList<>(rolesJsonArray.size()); for (int i = 0; i < rolesJsonArray.size(); i++) { roles.add((String) rolesJsonArray.get(i)); } return roles; } public Map> getResourceNameToAccessRolesMap(List resourcesToSkip) { Map> map = new HashMap<>(); Iterator resourcesIterator = getResourceAccessKeys(); while (resourcesIterator.hasNext()) { String resource = resourcesIterator.next(); if (resourcesToSkip.contains(resource)) { continue; } map.put(resource, getResourceAccessRoles(resource)); } return map; } protected JSONArray getAuthorizationPermissions() { JSONObject authorization = (JSONObject) getPayload().get("authorization"); return (JSONArray) authorization.get("permissions"); } public List getAuthorizationPermissionRSNames() { List permissionsRSName = new ArrayList<>(); JSONArray permissions = getAuthorizationPermissions(); for (int i = 0; i < permissions.size(); i++) { JSONObject permissionsEntry = (JSONObject) permissions.get(i); permissionsRSName.add((String) permissionsEntry.get("rsname")); } return permissionsRSName; } public List getAuthorizationPermissionRSNameResourceScopes(String rsname) { List scopes = new ArrayList<>(); JSONArray permissions = getAuthorizationPermissions(); for (int i = 0; i < permissions.size(); i++) { JSONObject permissionsEntry = (JSONObject) permissions.get(i); if (rsname.equals(permissionsEntry.get("rsname"))) { JSONArray scopesJsonArray = (JSONArray) permissionsEntry.get("resource_scopes"); if (scopesJsonArray != null) { for (int j = 0; j < scopesJsonArray.size(); j++) { scopes.add((String) scopesJsonArray.get(j)); } } } } return scopes; } public Map> getAuthorizationPermissionRSNameToResourceScopesMap() { Map> map = new HashMap<>(); for (String aprn : getAuthorizationPermissionRSNames()) { map.put(aprn, getAuthorizationPermissionRSNameResourceScopes(aprn)); } return map; } @Override public String toString() { return getRaw(); } }