diff --git a/CHANGELOG.md b/CHANGELOG.md
index ab89d6d..642f20b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
# Changelog for Common Smartgears
+## [v3.1.0] - 2021-05-14
+
+- use of AccessTokenProvider
+- use gcube-jackson instead of minimal-json for access token parsing [#21097]
+
+
## [v3.0.2] - 2020-03-01
- check if response is already committed on error
diff --git a/pom.xml b/pom.xml
index 9a1f612..84b8c5b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
org.gcube.core
common-smartgears
- 3.0.2
+ 3.1.0
SmartGears
@@ -19,7 +19,7 @@
org.gcube.distribution
gcube-bom
- 2.0.0
+ 2.0.1
pom
import
@@ -41,11 +41,21 @@
+
- com.eclipsesource.minimal-json
- minimal-json
- 0.9.4
+ org.gcube.common
+ gcube-jackson-databind
+
+ org.gcube.common
+ gcube-jackson-annotations
+
+
+ org.gcube.common
+ gcube-jackson-core
+
+
+
org.gcube.common
@@ -189,7 +199,7 @@
maven-jar-plugin
-
+
default-jar
@@ -233,7 +243,7 @@
org.apache.maven.plugins
maven-surefire-plugin
-
+
diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java
index 92af912..52af00e 100644
--- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java
+++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java
@@ -6,19 +6,16 @@ import static org.gcube.smartgears.Constants.token_header;
import static org.gcube.smartgears.handlers.application.request.RequestError.internal_server_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
import java.util.Base64;
-import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
+import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
import org.gcube.common.authorization.library.AuthorizationEntry;
+import org.gcube.common.authorization.library.provider.AccessTokenProvider;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
-import org.gcube.common.authorization.library.provider.UmaJWTProvider;
import org.gcube.common.authorization.library.provider.UserInfo;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
@@ -27,13 +24,10 @@ import org.gcube.smartgears.Constants;
import org.gcube.smartgears.handlers.application.RequestEvent;
import org.gcube.smartgears.handlers.application.RequestHandler;
import org.gcube.smartgears.handlers.application.ResponseEvent;
+import org.gcube.smartgears.utils.GcubeJwt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.eclipsesource.json.Json;
-import com.eclipsesource.json.JsonArray;
-import com.eclipsesource.json.JsonObject;
-
@XmlRootElement(name = Constants.request_context_retriever)
public class RequestContextRetriever extends RequestHandler {
@@ -55,46 +49,50 @@ public class RequestContextRetriever extends RequestHandler {
String authHeader = call.request().getHeader(Constants.authorization_header);
- log.trace("auth header is {}",authHeader);
+ log.trace("authorization header is {}",authHeader);
+ log.trace("token header is {}",token);
+ log.trace("scope header is {}",scope);
- String umaToken = null;
+ String retrievedUser = null;
+ String accessToken = null;
if (authHeader!=null && !authHeader.isEmpty()) {
if (authHeader.startsWith(BEARER_AUTH_PREFIX))
- umaToken = authHeader.substring(BEARER_AUTH_PREFIX.length()).trim();
+ accessToken = authHeader.substring(BEARER_AUTH_PREFIX.length()).trim();
else if (token==null && authHeader.startsWith(BASIC_AUTH_PREFIX)) {
String basicAuthToken = authHeader.substring(BASIC_AUTH_PREFIX.length()).trim();
String decodedAuth = new String(Base64.getDecoder().decode(basicAuthToken.getBytes()));
- token = decodedAuth.split(":")[1];
+ String[] splitAuth = decodedAuth.split(":");
+ token = splitAuth[1];
+ retrievedUser = splitAuth[0];
}
}
-
-
-
-
- //Gives priority to the token
- if (umaToken!=null) {
- this.retreiveAndSetInfoUmaToken(umaToken, token, call);
+
+ //Gives priority to the umaToken
+ if (accessToken!=null) {
+ this.retreiveAndSetInfoUmaToken(accessToken, token, call);
} else if (token!=null)
- this.retreiveAndSetInfoGcubeToken(token, call);
+ this.retreiveAndSetInfoGcubeToken(token, retrievedUser, call);
else if (scope!=null)
ScopeProvider.instance.set(scope);
-
+
}
@Override
public void handleResponse(ResponseEvent e) {
SecurityTokenProvider.instance.reset();
AuthorizationProvider.instance.reset();
- UmaJWTProvider.instance.reset();
+ AccessTokenProvider.instance.reset();
ScopeProvider.instance.reset();
log.debug("resetting all the Thread local for this call.");
}
- private void retreiveAndSetInfoGcubeToken(String token, RequestEvent call){
+ private void retreiveAndSetInfoGcubeToken(String token, String retrievedUser, RequestEvent call){
log.trace("retrieving context using token {} ", token);
AuthorizationEntry authEntry = null;
try{
authEntry = authorizationService().get(token);
+ if (retrievedUser != null && authEntry.getClientInfo().getId().equals(retrievedUser))
+ throw new Exception("user and token owner are not the same");
}catch(ObjectNotFound onf){
log.warn("rejecting call to {}, invalid token {}",call.context().name(),token);
invalid_request_error.fire(call.context().name()+" invalid token : "+token);
@@ -109,50 +107,44 @@ public class RequestContextRetriever extends RequestHandler {
log.info("retrieved request authorization info {} in scope {} ", AuthorizationProvider.instance.get(), authEntry.getContext());
}
- private void retreiveAndSetInfoUmaToken(String umaToken, String gcubeToken, RequestEvent call){
+ private void retreiveAndSetInfoUmaToken(String accessToken, String gcubeToken, RequestEvent call){
log.debug("using UMA token for authorization");
- log.trace("retrieving context using uma token {} ", umaToken);
+ log.trace("retrieving context using uma token {} ", accessToken);
- UmaJWTProvider.instance.set(umaToken);
+ AccessTokenProvider.instance.set(accessToken);
SecurityTokenProvider.instance.set(gcubeToken);
- parseUmaTokenAndSet(umaToken);
+ parseAccessTokenAndSet(accessToken);
log.info("retrieved request authorization info {} in scope {} ", AuthorizationProvider.instance.get(), ScopeProvider.instance.get());
}
- private void parseUmaTokenAndSet(String umaToken) {
+ private void parseAccessTokenAndSet(String umaToken) {
String realUmaTokenEncoded = umaToken.split("\\.")[1];
String realUmaToken = new String(Base64.getDecoder().decode(realUmaTokenEncoded.getBytes()));
+
+ ObjectMapper mapper = new ObjectMapper();
- JsonObject object = Json.parse(realUmaToken).asObject();
- String username = object.get("preferred_username").asString();
- String scope = object.getString("aud", null);
-
- log.trace("token related context is {}", scope);
-
- JsonObject resource = object.get("resource_access").asObject();
-
- log.trace("resource access is {}", resource.toString());
-
- JsonObject scopeObject = resource.get(scope).asObject();
+ GcubeJwt jwt = null;
+ try {
+ jwt = mapper.readValue(realUmaToken, GcubeJwt.class);
+ }catch(Exception e){
+ log.error("error decoding uma token",e);
+ internal_server_error.fire("error parsing access token");
+ }
+
ScopeBean scopeBean = null;
try {
- String decodedName = URLDecoder.decode(scope, StandardCharsets.UTF_8.toString());
- scopeBean = new ScopeBean(decodedName);
+ scopeBean = new ScopeBean(jwt.getContext());
}catch(Exception e){
log.error("error decoding uma token",e);
- internal_server_error.fire("error contacting authorization service");
+ internal_server_error.fire("invalid context in access token");
}
-
- JsonArray roles = scopeObject.get("roles").asArray();
-
- List userRoles = new ArrayList();
- roles.forEach((e)->userRoles.add(e.asString()));
- AuthorizationProvider.instance.set(new Caller(new UserInfo(username, userRoles), "token"));
+ AuthorizationProvider.instance.set(new Caller(new UserInfo(jwt.getUsername(), jwt.getRoles(), jwt.getEmail(), jwt.getFirstName(), jwt.getLastName()), "token"));
+
ScopeProvider.instance.set(scopeBean.toString());
}
diff --git a/src/main/java/org/gcube/smartgears/utils/GcubeJwt.java b/src/main/java/org/gcube/smartgears/utils/GcubeJwt.java
new file mode 100644
index 0000000..524d2b9
--- /dev/null
+++ b/src/main/java/org/gcube/smartgears/utils/GcubeJwt.java
@@ -0,0 +1,76 @@
+package org.gcube.smartgears.utils;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.gcube.com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import org.gcube.com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class GcubeJwt {
+
+ @JsonProperty("aud")
+ private String context;
+
+ @JsonProperty("resource_access")
+ private Map contextAccess = new HashMap<>();
+
+ @JsonProperty("preferred_username")
+ private String username;
+
+ @JsonProperty("given_name")
+ private String firstName;
+
+ @JsonProperty("family_name")
+ private String lastName;
+
+ @JsonProperty("email")
+ private String email;
+
+ public List getRoles(){
+ return contextAccess.get(this.context).roles;
+ }
+
+ public String getContext() {
+ try {
+ return URLDecoder.decode(context, StandardCharsets.UTF_8.toString());
+ }catch (UnsupportedEncodingException e) {
+ return context;
+ }
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ @Override
+ public String toString() {
+ return "GcubeJwt [context=" + getContext() + ", roles=" + getRoles() + ", username=" + username
+ + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]";
+ }
+
+ public static class Roles {
+
+ @JsonProperty("roles")
+ List roles = new ArrayList<>();
+
+ }
+
+}