diff --git a/.classpath b/.classpath
index 91f2707..ffa5a81 100644
--- a/.classpath
+++ b/.classpath
@@ -6,15 +6,11 @@
-
-
-
-
-
+
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index 443e085..8db228c 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -5,4 +5,5 @@ org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.7
diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component
index 0543109..b6f63af 100644
--- a/.settings/org.eclipse.wst.common.component
+++ b/.settings/org.eclipse.wst.common.component
@@ -1,5 +1,5 @@
-
+
diff --git a/pom.xml b/pom.xml
index 3372b09..c2e1c38 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,4 +1,5 @@
-
4.0.0
@@ -12,11 +13,11 @@
org.gcube.portal
oauth
war
- 1.0.1-SNAPSHOT
+ 1.1.0-SNAPSHOT
gcube-oauth
- 1.7
+ 1.8
2.22.1
${project.basedir}/distro
${project.build.directory}/${project.build.finalName}
@@ -44,6 +45,11 @@
+
+ net.spy
+ spymemcached
+ 2.12.3
+
org.glassfish.jersey.containers
diff --git a/src/main/java/org/gcube/portal/oauth/OauthService.java b/src/main/java/org/gcube/portal/oauth/OauthService.java
index b183760..b6d8e44 100644
--- a/src/main/java/org/gcube/portal/oauth/OauthService.java
+++ b/src/main/java/org/gcube/portal/oauth/OauthService.java
@@ -2,9 +2,8 @@ package org.gcube.portal.oauth;
import static org.gcube.common.authorization.client.Constants.authorizationService;
+import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Singleton;
import javax.servlet.http.HttpServletRequest;
@@ -26,13 +25,13 @@ import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portal.oauth.cache.CacheBean;
-import org.gcube.portal.oauth.cache.CacheCleaner;
import org.gcube.portal.oauth.input.PushCodeBean;
import org.gcube.portal.oauth.output.AccessTokenBeanResponse;
import org.gcube.portal.oauth.output.AccessTokenErrorResponse;
-import org.gcube.smartgears.Constants;
import org.slf4j.LoggerFactory;
+import net.spy.memcached.MemcachedClient;
+
@Path("/v2")
@Singleton
@@ -40,21 +39,18 @@ public class OauthService {
public static final String OAUTH_TOKEN_GET_METHOD_NAME_REQUEST = "access-token";
private static final String GRANT_TYPE_VALUE = "authorization_code";
-
private static final String AUTHORIZATION_HEADER = "Authorization";
+ private static final int CACHE_SECONDS_EXPIRATION = 10;
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(OauthService.class);
/**
* This map contains couples
*/
- private Map entries;
+ private MemcachedClient entries;
+
- /**
- * Cleaner thread
- */
- CacheCleaner cleaner;
/**
* Since this is a singleton sub-service, there will be just one call to this constructor and one running thread
@@ -62,15 +58,12 @@ public class OauthService {
*/
public OauthService() {
logger.info("Singleton gcube-oauth service built.");
- entries = new ConcurrentHashMap();
- cleaner = new CacheCleaner(entries);
- cleaner.start();
+ entries = DistributedCacheClient.getInstance().getMemcachedClient();
}
@Override
protected void finalize(){
- if(cleaner != null)
- cleaner.interrupt();
+ entries.shutdown();
}
/**
@@ -106,12 +99,14 @@ public class OauthService {
@Produces(MediaType.APPLICATION_JSON)
@Path("push-authentication-code")
/**
+ * CALLED FROM THE PORTAL PORTLET to pass among the other the temp code which expires in 10 seconds
+ *
* The portal will push a qualified token together a code
* @return Response with status 201 if the code has been saved correctly
*/
public Response pushAuthCode(PushCodeBean bean) {
- logger.info("Request to push ");
+ logger.info("Request to push aothCode from the portal ");
Caller caller = AuthorizationProvider.instance.get();
String token = SecurityTokenProvider.instance.get();
@@ -141,7 +136,7 @@ public class OauthService {
entity("{\"error\"=\"'redirect_uri' cannot be null or missing\"").build();
logger.info("Saving entry defined by " + bean + " in cache, token is " + token.substring(0, 10) + "***************");
- entries.put(code, new CacheBean(token, ScopeProvider.instance.get(), redirectUri, clientId, System.currentTimeMillis()));
+ entries.set(code, CACHE_SECONDS_EXPIRATION, new CacheBean(token, ScopeProvider.instance.get(), redirectUri, clientId));
return Response.status(status).build();
}
@@ -194,8 +189,8 @@ public class OauthService {
return Response.status(status).entity(new AccessTokenErrorResponse(errorMessage, null)).build();
}else{
logger.info("The request is ok");
- String tokenToReturn = entries.get(code).getToken();
- String scope = entries.get(code).getScope();
+ String tokenToReturn = ((CacheBean) entries.get(code)).getToken();
+ String scope = ((CacheBean)entries.get(code)).getScope();
status = Status.OK;
return Response.status(status).entity(new AccessTokenBeanResponse(tokenToReturn, scope)).build();
}
@@ -212,8 +207,15 @@ public class OauthService {
String credentials = new String(DatatypeConverter.parseBase64Binary(base64Credentials));
// credentials = username:password
String[] splitCreds = credentials.split(":");
- String clientId = URLDecoder.decode(splitCreds[0]);
- String clientSecret = URLDecoder.decode(splitCreds[1]);
+ String clientId = null;
+ String clientSecret = null;
+ try {
+ clientId = URLDecoder.decode(splitCreds[0], java.nio.charset.StandardCharsets.UTF_8.toString());
+ clientSecret = URLDecoder.decode(splitCreds[1], java.nio.charset.StandardCharsets.UTF_8.toString());
+ } catch (UnsupportedEncodingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
return new CredentialsBean(clientId, clientSecret);
}
@@ -236,9 +238,9 @@ public class OauthService {
return "invalid_request";
if(!checkIsapplicationTokenType(authorizationService().get(credentials.getClientSecret()).getClientInfo().getType())) // it is not an app token or it is not a token
return "invalid_client";
- if(!entries.containsKey(code) || CacheBean.isExpired(entries.get(code)))
+ if(entries.get(code) == null)
return "invalid_grant";
- CacheBean entry = entries.get(code);
+ CacheBean entry = (CacheBean) entries.get(code);
if(!entry.getRedirectUri().equals(redirectUri) || !entry.getClientId().equals(credentials.getClientId()))
return "invalid_grant";
if(!grantType.equals(GRANT_TYPE_VALUE))
diff --git a/src/main/java/org/gcube/portal/oauth/cache/CacheBean.java b/src/main/java/org/gcube/portal/oauth/cache/CacheBean.java
index a904be9..899ad78 100644
--- a/src/main/java/org/gcube/portal/oauth/cache/CacheBean.java
+++ b/src/main/java/org/gcube/portal/oauth/cache/CacheBean.java
@@ -1,19 +1,25 @@
package org.gcube.portal.oauth.cache;
+import java.io.Serializable;
+
/**
* A cache bean object for oauth support
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
+ * @author Massimiliano Assante, National Research Council of Italy (CNR) - ISTI
*/
-public class CacheBean {
+@SuppressWarnings("serial")
+public class CacheBean implements Serializable {
private String token;
private String scope;
private String redirectUri;
private String clientId;
- private Long insertTime;
- private static final int TOKEN_TTL = 1000 * 10;
+ public CacheBean() {
+ super();
+ }
+
/**
* @param token
* @param scope
@@ -21,14 +27,12 @@ public class CacheBean {
* @param clientId
* @param insertTime
*/
- public CacheBean(String token, String scope, String redirectUri,
- String clientId, Long insertTime) {
+ public CacheBean(String token, String scope, String redirectUri, String clientId) {
super();
this.token = token;
this.scope = scope;
this.redirectUri = redirectUri;
this.clientId = clientId;
- this.insertTime = insertTime;
}
public String getScope() {
@@ -47,14 +51,6 @@ public class CacheBean {
this.token = token;
}
- public Long getInsertTime() {
- return insertTime;
- }
-
- public void setInsertTime(Long insertTime) {
- this.insertTime = insertTime;
- }
-
public String getRedirectUri() {
return redirectUri;
}
@@ -73,19 +69,16 @@ public class CacheBean {
@Override
public String toString() {
- return "CacheBean [token=" + token + ", scope=" + scope
- + ", redirectUri=" + redirectUri + ", clientId=" + clientId
- + ", insertTime=" + insertTime + "]";
- }
-
- /**
- * True if the code expired, false otherwise
- * @return
- */
- public static boolean isExpired(CacheBean bean){
-
- return System.currentTimeMillis() > TOKEN_TTL + bean.insertTime;
-
- }
-
+ StringBuilder builder = new StringBuilder();
+ builder.append("CacheBean [token=");
+ builder.append(token);
+ builder.append(", scope=");
+ builder.append(scope);
+ builder.append(", redirectUri=");
+ builder.append(redirectUri);
+ builder.append(", clientId=");
+ builder.append(clientId);
+ builder.append("]");
+ return builder.toString();
+ }
}