keycloak-aplcache

Details

diff --git a/services/src/main/java/org/keycloak/authentication/actiontoken/AbstractActionTokenHander.java b/services/src/main/java/org/keycloak/authentication/actiontoken/AbstractActionTokenHander.java
index 52d94d9..ccdc2f8 100644
--- a/services/src/main/java/org/keycloak/authentication/actiontoken/AbstractActionTokenHander.java
+++ b/services/src/main/java/org/keycloak/authentication/actiontoken/AbstractActionTokenHander.java
@@ -20,6 +20,7 @@ import org.keycloak.Config.Scope;
 import org.keycloak.events.EventType;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.representations.JsonWebToken;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.sessions.AuthenticationSessionModel;
 
@@ -27,7 +28,7 @@ import org.keycloak.sessions.AuthenticationSessionModel;
  *
  * @author hmlnarik
  */
-public abstract class AbstractActionTokenHander<T extends DefaultActionToken> implements ActionTokenHandler<T>, ActionTokenHandlerFactory<T> {
+public abstract class AbstractActionTokenHander<T extends JsonWebToken> implements ActionTokenHandler<T>, ActionTokenHandlerFactory<T> {
 
     private final String id;
     private final Class<T> tokenClass;
@@ -86,8 +87,8 @@ public abstract class AbstractActionTokenHander<T extends DefaultActionToken> im
     }
 
     @Override
-    public String getAuthenticationSessionIdFromToken(T token) {
-        return token == null ? null : token.getAuthenticationSessionId();
+    public String getAuthenticationSessionIdFromToken(T token, ActionTokenContext<T> tokenContext) {
+        return token instanceof DefaultActionToken ? ((DefaultActionToken) token).getAuthenticationSessionId() : null;
     }
 
     @Override
diff --git a/services/src/main/java/org/keycloak/authentication/actiontoken/ActionTokenHandler.java b/services/src/main/java/org/keycloak/authentication/actiontoken/ActionTokenHandler.java
index f8d02d3..b61c9c0 100644
--- a/services/src/main/java/org/keycloak/authentication/actiontoken/ActionTokenHandler.java
+++ b/services/src/main/java/org/keycloak/authentication/actiontoken/ActionTokenHandler.java
@@ -64,7 +64,7 @@ public interface ActionTokenHandler<T extends JsonWebToken> extends Provider {
      * @param token Token. Can be {@code null}
      * @return authentication session ID
      */
-    String getAuthenticationSessionIdFromToken(T token);
+    String getAuthenticationSessionIdFromToken(T token, ActionTokenContext<T> tokenContext);
 
     /**
      * Returns a event type logged with {@link EventBuilder} class.
diff --git a/services/src/main/java/org/keycloak/authentication/actiontoken/DefaultActionToken.java b/services/src/main/java/org/keycloak/authentication/actiontoken/DefaultActionToken.java
index ba44880..0f514d0 100644
--- a/services/src/main/java/org/keycloak/authentication/actiontoken/DefaultActionToken.java
+++ b/services/src/main/java/org/keycloak/authentication/actiontoken/DefaultActionToken.java
@@ -39,7 +39,7 @@ public class DefaultActionToken extends DefaultActionTokenKey implements ActionT
 
     public static final String JSON_FIELD_AUTHENTICATION_SESSION_ID = "asid";
 
-    public static final Predicate<DefaultActionToken> ACTION_TOKEN_BASIC_CHECKS = t -> {
+    public static final Predicate<DefaultActionTokenKey> ACTION_TOKEN_BASIC_CHECKS = t -> {
         if (t.getActionVerificationNonce() == null) {
             throw new VerificationException("Nonce not present.");
         }
@@ -131,7 +131,7 @@ public class DefaultActionToken extends DefaultActionTokenKey implements ActionT
      * <li>{@code issuer}: URI of the given realm</li>
      * <li>{@code audience}: URI of the given realm (same as issuer)</li>
      * </ul>
-     * 
+     *
      * @param session
      * @param realm
      * @param uri
diff --git a/services/src/main/java/org/keycloak/authentication/actiontoken/DefaultActionTokenKey.java b/services/src/main/java/org/keycloak/authentication/actiontoken/DefaultActionTokenKey.java
index b41681f..cc4ba32 100644
--- a/services/src/main/java/org/keycloak/authentication/actiontoken/DefaultActionTokenKey.java
+++ b/services/src/main/java/org/keycloak/authentication/actiontoken/DefaultActionTokenKey.java
@@ -36,6 +36,9 @@ public class DefaultActionTokenKey extends JsonWebToken implements ActionTokenKe
     @JsonProperty(value = JSON_FIELD_ACTION_VERIFICATION_NONCE, required = true)
     private UUID actionVerificationNonce;
 
+    public DefaultActionTokenKey() {
+    }
+
     public DefaultActionTokenKey(String userId, String actionId, int absoluteExpirationInSecs, UUID actionVerificationNonce) {
         this.subject = userId;
         this.type = actionId;
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index 054cc6e..5e8b0fe 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -16,7 +16,6 @@
  */
 package org.keycloak.services.resources;
 
-import org.keycloak.authentication.actiontoken.DefaultActionToken;
 import org.keycloak.authentication.actiontoken.DefaultActionTokenKey;
 import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.HttpRequest;
@@ -27,6 +26,7 @@ import org.keycloak.authentication.RequiredActionContextResult;
 import org.keycloak.authentication.RequiredActionFactory;
 import org.keycloak.authentication.RequiredActionProvider;
 import org.keycloak.TokenVerifier;
+import org.keycloak.authentication.ExplainedVerificationException;
 import org.keycloak.authentication.actiontoken.*;
 import org.keycloak.authentication.actiontoken.resetcred.ResetCredentialsActionTokenHandler;
 import org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator;
@@ -59,6 +59,7 @@ import org.keycloak.protocol.LoginProtocol.Error;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.protocol.oidc.utils.OIDCResponseMode;
 import org.keycloak.protocol.oidc.utils.OIDCResponseType;
+import org.keycloak.representations.JsonWebToken;
 import org.keycloak.services.ErrorPage;
 import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.Urls;
@@ -405,7 +406,7 @@ public class LoginActionsService {
         return handleActionToken(key, execution, clientId);
     }
 
-    protected <T extends DefaultActionToken> Response handleActionToken(String tokenString, String execution, String clientId) {
+    protected <T extends DefaultActionTokenKey> Response handleActionToken(String tokenString, String execution, String clientId) {
         T token;
         ActionTokenHandler<T> handler;
         ActionTokenContext<T> tokenContext;
@@ -430,8 +431,8 @@ public class LoginActionsService {
                 throw new ExplainedTokenVerificationException(null, Errors.NOT_ALLOWED, Messages.INVALID_REQUEST);
             }
 
-            TokenVerifier<DefaultActionToken> tokenVerifier = TokenVerifier.create(tokenString, DefaultActionToken.class);
-            DefaultActionToken aToken = tokenVerifier.getToken();
+            TokenVerifier<DefaultActionTokenKey> tokenVerifier = TokenVerifier.create(tokenString, DefaultActionTokenKey.class);
+            DefaultActionTokenKey aToken = tokenVerifier.getToken();
 
             event
               .detail(Details.TOKEN_ID, aToken.getId())
@@ -477,6 +478,8 @@ public class LoginActionsService {
             return handleActionTokenVerificationException(null, ex, Errors.EXPIRED_CODE, Messages.EXPIRED_ACTION_TOKEN_NO_SESSION);
         } catch (ExplainedTokenVerificationException ex) {
             return handleActionTokenVerificationException(null, ex, ex.getErrorEvent(), ex.getMessage());
+        } catch (ExplainedVerificationException ex) {
+            return handleActionTokenVerificationException(null, ex, ex.getErrorEvent(), ex.getMessage());
         } catch (VerificationException ex) {
             return handleActionTokenVerificationException(null, ex, eventError, defaultErrorMessage);
         }
@@ -485,7 +488,7 @@ public class LoginActionsService {
         tokenContext = new ActionTokenContext(session, realm, uriInfo, clientConnection, request, event, handler, execution, this::processFlow, this::brokerLoginFlow);
 
         try {
-            String tokenAuthSessionId = handler.getAuthenticationSessionIdFromToken(token);
+            String tokenAuthSessionId = handler.getAuthenticationSessionIdFromToken(token, tokenContext);
 
             if (tokenAuthSessionId != null) {
                 // This can happen if the token contains ID but user opens the link in a new browser
@@ -541,7 +544,6 @@ public class LoginActionsService {
         }
     }
 
-
     private Response processFlowFromPath(String flowPath, AuthenticationSessionModel authSession, String errorMessage) {
         if (AUTHENTICATE_PATH.equals(flowPath)) {
             return processAuthentication(false, null, authSession, errorMessage);
@@ -555,7 +557,7 @@ public class LoginActionsService {
     }
 
 
-    private <T extends DefaultActionToken> ActionTokenHandler<T> resolveActionTokenHandler(String actionId) throws VerificationException {
+    private <T extends JsonWebToken> ActionTokenHandler<T> resolveActionTokenHandler(String actionId) throws VerificationException {
         if (actionId == null) {
             throw new VerificationException("Action token operation not set");
         }
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsServiceChecks.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsServiceChecks.java
index 9edc513..b9031cb 100644
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsServiceChecks.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsServiceChecks.java
@@ -18,7 +18,7 @@ package org.keycloak.services.resources;
 
 import org.keycloak.TokenVerifier.Predicate;
 import org.keycloak.authentication.AuthenticationProcessor;
-import org.keycloak.authentication.actiontoken.DefaultActionToken;
+import org.keycloak.authentication.actiontoken.DefaultActionTokenKey;
 import org.keycloak.authentication.ExplainedVerificationException;
 import org.keycloak.authentication.actiontoken.ActionTokenContext;
 import org.keycloak.authentication.actiontoken.ExplainedTokenVerificationException;
@@ -152,7 +152,7 @@ public class LoginActionsServiceChecks {
      *  Verifies whether the user given by ID both exists in the current realm. If yes,
      *  it optionally also injects the user using the given function (e.g. into session context).
      */
-    public static <T extends DefaultActionToken> void checkIsUserValid(T token, ActionTokenContext<T> context) throws VerificationException {
+    public static <T extends DefaultActionTokenKey> void checkIsUserValid(T token, ActionTokenContext<T> context) throws VerificationException {
         try {
             checkIsUserValid(context.getSession(), context.getRealm(), token.getUserId(), context.getAuthenticationSession()::setAuthenticatedUser);
         } catch (ExplainedVerificationException ex) {
@@ -178,7 +178,7 @@ public class LoginActionsServiceChecks {
      * Verifies whether the client denoted by client ID in token's {@code iss} ({@code issuedFor})
      * field both exists and is enabled.
      */
-    public static <T extends DefaultActionToken> void checkIsClientValid(T token, ActionTokenContext<T> context) throws VerificationException {
+    public static <T extends JsonWebToken> void checkIsClientValid(T token, ActionTokenContext<T> context) throws VerificationException {
         String clientId = token.getIssuedFor();
         AuthenticationSessionModel authSession = context.getAuthenticationSession();
         ClientModel client = authSession == null ? null : authSession.getClient();
@@ -297,8 +297,9 @@ public class LoginActionsServiceChecks {
         return true;
     }
 
-    public static <T extends DefaultActionToken> void checkTokenWasNotUsedYet(T token, ActionTokenContext<T> context) throws VerificationException {
+    public static <T extends DefaultActionTokenKey> void checkTokenWasNotUsedYet(T token, ActionTokenContext<T> context) throws VerificationException {
         ActionTokenStoreProvider actionTokenStore = context.getSession().getProvider(ActionTokenStoreProvider.class);
+
         if (actionTokenStore.get(token) != null) {
             throw new ExplainedTokenVerificationException(token, Errors.EXPIRED_CODE, Messages.EXPIRED_ACTION);
         }