Repository: jclouds
Updated Branches:
  refs/heads/master 9662edf90 -> 0fd013da0


JCLOUDS-1148: Fix token caches in OAuth flows


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/913fdeb1
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/913fdeb1
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/913fdeb1

Branch: refs/heads/master
Commit: 913fdeb168db948d59c58531efa0a413332b3f71
Parents: 9662edf
Author: Daniel Haeser Rech <[email protected]>
Authored: Wed Aug 3 22:54:22 2016 -0300
Committer: Ignasi Barrera <[email protected]>
Committed: Thu Sep 1 09:55:23 2016 +0200

----------------------------------------------------------------------
 .../jclouds/oauth/v2/domain/ClientSecret.java   |  9 ++--
 .../ClientCredentialsJWTBearerTokenFlow.java    | 32 ++++++++------
 .../v2/filters/ClientCredentialsSecretFlow.java | 10 +----
 .../oauth/v2/filters/JWTBearerTokenFlow.java    | 44 +++++++++++++++-----
 4 files changed, 58 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/913fdeb1/apis/oauth/src/main/java/org/jclouds/oauth/v2/domain/ClientSecret.java
----------------------------------------------------------------------
diff --git 
a/apis/oauth/src/main/java/org/jclouds/oauth/v2/domain/ClientSecret.java 
b/apis/oauth/src/main/java/org/jclouds/oauth/v2/domain/ClientSecret.java
index c006ca1..2ec45a5 100644
--- a/apis/oauth/src/main/java/org/jclouds/oauth/v2/domain/ClientSecret.java
+++ b/apis/oauth/src/main/java/org/jclouds/oauth/v2/domain/ClientSecret.java
@@ -38,12 +38,9 @@ public abstract class ClientSecret {
     /** The scope(s) to authorize against. **/
     @Nullable public abstract String scope();
 
-    /** When does the token expire. **/
-    public abstract long expire();
-
-    @SerializedNames({ "client_id", "client_secret", "resource", "scope", 
"expire" })
-    public static ClientSecret create(String clientId, String clientSecret, 
String resource, String scope, long expire) {
-        return new AutoValue_ClientSecret(clientId, clientSecret, resource, 
scope, expire);
+    @SerializedNames({ "client_id", "client_secret", "resource", "scope" })
+    public static ClientSecret create(String clientId, String clientSecret, 
String resource, String scope) {
+        return new AutoValue_ClientSecret(clientId, clientSecret, resource, 
scope);
     }
 
     ClientSecret() {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/913fdeb1/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/ClientCredentialsJWTBearerTokenFlow.java
----------------------------------------------------------------------
diff --git 
a/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/ClientCredentialsJWTBearerTokenFlow.java
 
b/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/ClientCredentialsJWTBearerTokenFlow.java
index dd11940..dccb7f5 100644
--- 
a/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/ClientCredentialsJWTBearerTokenFlow.java
+++ 
b/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/ClientCredentialsJWTBearerTokenFlow.java
@@ -58,7 +58,6 @@ public class ClientCredentialsJWTBearerTokenFlow implements 
OAuthFilter {
     private final String audience;
     private final Supplier<Credentials> credentialsSupplier;
     private final OAuthScopes scopes;
-    private final long tokenDuration;
     private final LoadingCache<ClientCredentialsAuthArgs, Token> tokenCache;
 
     @Inject
@@ -71,7 +70,6 @@ public class ClientCredentialsJWTBearerTokenFlow implements 
OAuthFilter {
         this.scopes = scopes;
         this.audience = audience;
         this.resource = resource;
-        this.tokenDuration = tokenDuration;
         // since the session interval is also the token expiration time 
requested to the server make the token expire a
         // bit before the deadline to make sure there aren't session 
expiration exceptions
         long cacheExpirationSeconds = tokenDuration > 30 ? tokenDuration - 30 
: tokenDuration;
@@ -80,26 +78,40 @@ public class ClientCredentialsJWTBearerTokenFlow implements 
OAuthFilter {
 
     static final class AuthorizeToken extends 
CacheLoader<ClientCredentialsAuthArgs, Token> {
         private final AuthorizationApi api;
+        private final long tokenDuration;
 
-        @Inject AuthorizeToken(AuthorizationApi api) {
+        @Inject AuthorizeToken(AuthorizationApi api, 
@Named(PROPERTY_SESSION_INTERVAL) long tokenDuration) {
             this.api = api;
+            this.tokenDuration = tokenDuration;
+        }
+
+        long currentTimeSeconds() {
+            return System.currentTimeMillis() / 1000;
         }
 
         @Override public Token load(ClientCredentialsAuthArgs key) throws 
Exception {
-            return api.authorize(key.clientId(), key.claims(), key.resource(), 
key.scope());
+            final long now = currentTimeSeconds();
+            final ClientCredentialsClaims claims = 
ClientCredentialsClaims.create(
+                  key.claims().iss(),
+                  key.claims().sub(),
+                  key.claims().aud(),
+                  now + tokenDuration,
+                  now,
+                  UUID.randomUUID().toString()
+            );
+            return api.authorize(key.clientId(), claims, key.resource(), 
key.scope());
         }
     }
 
     @Override public HttpRequest filter(HttpRequest request) throws 
HttpException {
-        long now = currentTimeSeconds();
         List<String> configuredScopes = scopes.forRequest(request);
         ClientCredentialsClaims claims = ClientCredentialsClaims.create( //
                 credentialsSupplier.get().identity, // iss
                 credentialsSupplier.get().identity, // sub
                 audience, // aud
-                now + tokenDuration, // exp
-                now, // nbf
-                UUID.randomUUID().toString() // jti
+                -1, // placeholder exp for the cache
+                -1, // placeholder nbf for the cache
+                null // placeholder jti for the cache
         );
         ClientCredentialsAuthArgs authArgs = ClientCredentialsAuthArgs.create(
                 credentialsSupplier.get().identity,
@@ -112,9 +124,5 @@ public class ClientCredentialsJWTBearerTokenFlow implements 
OAuthFilter {
         String authorization = String.format("%s %s", token.tokenType(), 
token.accessToken());
         return request.toBuilder().addHeader("Authorization", 
authorization).build();
     }
-
-    long currentTimeSeconds() {
-        return System.currentTimeMillis() / 1000;
-    }
 }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/913fdeb1/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/ClientCredentialsSecretFlow.java
----------------------------------------------------------------------
diff --git 
a/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/ClientCredentialsSecretFlow.java
 
b/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/ClientCredentialsSecretFlow.java
index f6e3534..d721865 100644
--- 
a/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/ClientCredentialsSecretFlow.java
+++ 
b/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/ClientCredentialsSecretFlow.java
@@ -55,7 +55,6 @@ public class ClientCredentialsSecretFlow implements 
OAuthFilter {
     private static final Joiner ON_SPACE = Joiner.on(" ");
 
     private final Supplier<Credentials> credentialsSupplier;
-    private final long tokenDuration;
     private final LoadingCache<ClientSecret, Token> tokenCache;
     private final String resource;
     private final OAuthScopes scopes;
@@ -67,7 +66,6 @@ public class ClientCredentialsSecretFlow implements 
OAuthFilter {
         this.credentialsSupplier = credentialsSupplier;
         this.scopes = scopes;
         this.resource = resource;
-        this.tokenDuration = tokenDuration;
         // since the session interval is also the token expiration time 
requested to the server make the token expire a
         // bit before the deadline to make sure there aren't session 
expiration exceptions
         long cacheExpirationSeconds = tokenDuration > 30 ? tokenDuration - 30 
: tokenDuration;
@@ -87,21 +85,15 @@ public class ClientCredentialsSecretFlow implements 
OAuthFilter {
     }
 
     @Override public HttpRequest filter(HttpRequest request) throws 
HttpException {
-        long now = currentTimeSeconds();
         List<String> configuredScopes = scopes.forRequest(request);
         ClientSecret client = ClientSecret.create(
                 credentialsSupplier.get().identity,
                 credentialsSupplier.get().credential,
                 resource == null ? "" : resource,
-                configuredScopes.isEmpty() ? null : 
ON_SPACE.join(configuredScopes),
-                now + tokenDuration
+                configuredScopes.isEmpty() ? null : 
ON_SPACE.join(configuredScopes)
         );
         Token token = tokenCache.getUnchecked(client);
         String authorization = String.format("%s %s", token.tokenType(), 
token.accessToken());
         return request.toBuilder().addHeader("Authorization", 
authorization).build();
     }
-
-    long currentTimeSeconds() {
-        return System.currentTimeMillis() / 1000;
-    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/913fdeb1/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/JWTBearerTokenFlow.java
----------------------------------------------------------------------
diff --git 
a/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/JWTBearerTokenFlow.java 
b/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/JWTBearerTokenFlow.java
index 7f2729f..43ec549 100644
--- 
a/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/JWTBearerTokenFlow.java
+++ 
b/apis/oauth/src/main/java/org/jclouds/oauth/v2/filters/JWTBearerTokenFlow.java
@@ -32,6 +32,7 @@ import org.jclouds.oauth.v2.config.OAuthScopes;
 import org.jclouds.oauth.v2.domain.Claims;
 import org.jclouds.oauth.v2.domain.Token;
 
+import com.google.auto.value.AutoValue;
 import com.google.common.base.Joiner;
 import com.google.common.base.Supplier;
 import com.google.common.cache.CacheBuilder;
@@ -53,30 +54,36 @@ public class JWTBearerTokenFlow implements OAuthFilter {
    private final String audience;
    private final Supplier<Credentials> credentialsSupplier;
    private final OAuthScopes scopes;
-   private final long tokenDuration;
-   private final LoadingCache<Claims, Token> tokenCache;
+   private final LoadingCache<TokenCacheKey, Token> tokenCache;
 
    @Inject JWTBearerTokenFlow(AuthorizeToken loader, 
@Named(PROPERTY_SESSION_INTERVAL) long tokenDuration,
          @Provider Supplier<Credentials> credentialsSupplier, OAuthScopes 
scopes, @Named(AUDIENCE) String audience) {
       this.credentialsSupplier = credentialsSupplier;
       this.scopes = scopes;
       this.audience = audience;
-      this.tokenDuration = tokenDuration;
       // since the session interval is also the token expiration time 
requested to the server make the token expire a
       // bit before the deadline to make sure there aren't session expiration 
exceptions
       long cacheExpirationSeconds = tokenDuration > 30 ? tokenDuration - 30 : 
tokenDuration;
       this.tokenCache = 
CacheBuilder.newBuilder().expireAfterWrite(cacheExpirationSeconds, 
SECONDS).build(loader);
    }
 
-   static final class AuthorizeToken extends CacheLoader<Claims, Token> {
+   static final class AuthorizeToken extends CacheLoader<TokenCacheKey, Token> 
{
       private final AuthorizationApi api;
+      private final long tokenDuration;
 
-      @Inject AuthorizeToken(AuthorizationApi api) {
+      @Inject AuthorizeToken(AuthorizationApi api, 
@Named(PROPERTY_SESSION_INTERVAL) long tokenDuration) {
          this.api = api;
+         this.tokenDuration = tokenDuration;
       }
 
-      @Override public Token load(Claims key) throws Exception {
-         return api.authorize(key);
+      @Override public Token load(TokenCacheKey tokenCacheKey) throws 
Exception {
+         final Claims claims = Claims.create(
+               tokenCacheKey.claims().iss(),
+               tokenCacheKey.claims().scope(),
+               tokenCacheKey.claims().aud(),
+               tokenCacheKey.startTime + tokenDuration,
+               tokenCacheKey.startTime);
+         return api.authorize(claims);
       }
    }
 
@@ -86,10 +93,11 @@ public class JWTBearerTokenFlow implements OAuthFilter {
             credentialsSupplier.get().identity, // iss
             ON_COMMA.join(scopes.forRequest(request)), // scope
             audience, // aud
-            now + tokenDuration, // exp
-            now // iat
+            -1, // placeholder exp for the cache
+            -1 // placeholder iat for the cache
       );
-      Token token = tokenCache.getUnchecked(claims);
+      final TokenCacheKey tokenCacheKey = TokenCacheKey.create(claims, now);
+      Token token = tokenCache.getUnchecked(tokenCacheKey);
       String authorization = String.format("%s %s", token.tokenType(), 
token.accessToken());
       return request.toBuilder().addHeader("Authorization", 
authorization).build();
    }
@@ -97,4 +105,20 @@ public class JWTBearerTokenFlow implements OAuthFilter {
    long currentTimeSeconds() {
       return System.currentTimeMillis() / 1000;
    }
+
+   @AutoValue
+   abstract static class TokenCacheKey {
+      public abstract Claims claims();
+
+      long startTime;
+
+      public static TokenCacheKey create(Claims claims, long startTime) {
+         final AutoValue_JWTBearerTokenFlow_TokenCacheKey tokenCacheKey = new 
AutoValue_JWTBearerTokenFlow_TokenCacheKey(claims);
+         tokenCacheKey.startTime = startTime;
+         return tokenCacheKey;
+      }
+
+      TokenCacheKey() {
+      }
+   }
 }

Reply via email to