keycloak-aplcache

[KEYCLOAK-7822] - Fix access token and refresh token timeout

7/10/2018 1:55:26 PM

Details

diff --git a/authz/client/src/main/java/org/keycloak/authorization/client/util/TokenCallable.java b/authz/client/src/main/java/org/keycloak/authorization/client/util/TokenCallable.java
index b1c3280..ffaa592 100644
--- a/authz/client/src/main/java/org/keycloak/authorization/client/util/TokenCallable.java
+++ b/authz/client/src/main/java/org/keycloak/authorization/client/util/TokenCallable.java
@@ -18,15 +18,19 @@ package org.keycloak.authorization.client.util;
 
 import java.util.concurrent.Callable;
 
+import org.jboss.logging.Logger;
 import org.keycloak.authorization.client.Configuration;
 import org.keycloak.authorization.client.representation.ServerConfiguration;
+import org.keycloak.common.util.Time;
 import org.keycloak.jose.jws.JWSInput;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.representations.RefreshToken;
 import org.keycloak.util.JsonSerialization;
 
 public class TokenCallable implements Callable<String> {
 
+    private static Logger log = Logger.getLogger(TokenCallable.class);
     private final String userName;
     private final String password;
     private final Http http;
@@ -54,6 +58,22 @@ public class TokenCallable implements Callable<String> {
             } else {
                 clientToken = obtainAccessToken(userName, password);
             }
+        } else {
+            String refreshTokenValue = clientToken.getRefreshToken();
+            try {
+                RefreshToken refreshToken = JsonSerialization.readValue(new JWSInput(refreshTokenValue).getContent(), RefreshToken.class);
+                if (!refreshToken.isActive() || !isTokenTimeToLiveSufficient(refreshToken)) {
+                    log.debug("Refresh token is expired.");
+                    if (userName == null || password == null) {
+                        clientToken = obtainAccessToken();
+                    } else {
+                        clientToken = obtainAccessToken(userName, password);
+                    }
+                }
+            } catch (Exception e) {
+                clientToken = null;
+                throw new RuntimeException(e);
+            }
         }
 
         String token = clientToken.getToken();
@@ -61,8 +81,10 @@ public class TokenCallable implements Callable<String> {
         try {
             AccessToken accessToken = JsonSerialization.readValue(new JWSInput(token).getContent(), AccessToken.class);
 
-            if (accessToken.isActive()) {
+            if (accessToken.isActive() && this.isTokenTimeToLiveSufficient(accessToken)) {
                 return token;
+            } else {
+                log.debug("Access token is expired.");
             }
 
             clientToken = http.<AccessTokenResponse>post(serverConfiguration.getTokenEndpoint())
@@ -81,6 +103,10 @@ public class TokenCallable implements Callable<String> {
         return clientToken.getToken();
     }
 
+    public boolean isTokenTimeToLiveSufficient(AccessToken token) {
+        return token != null && (token.getExpiration() - getConfiguration().getTokenMinimumTimeToLive()) > Time.currentTime();
+    }
+
     /**
      * Obtains an access token using the client credentials.
      *