keycloak-aplcache

KEYCLOAK-5721 Moved state checker from separate cookie to

11/10/2017 10:39:56 AM

Details

diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index 1e8a53d..38c43da 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -30,6 +30,7 @@ import org.keycloak.authentication.actiontoken.DefaultActionTokenKey;
 import org.keycloak.broker.provider.IdentityProvider;
 import org.keycloak.common.ClientConnection;
 import org.keycloak.common.VerificationException;
+import org.keycloak.common.util.Base64Url;
 import org.keycloak.common.util.Time;
 import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
@@ -477,7 +478,7 @@ public class AuthenticationManager {
     }
 
 
-    public static AccessToken createIdentityToken(RealmModel realm, UserModel user, UserSessionModel session, String issuer) {
+    public static AccessToken createIdentityToken(KeycloakSession keycloakSession, RealmModel realm, UserModel user, UserSessionModel session, String issuer) {
         AccessToken token = new AccessToken();
         token.id(KeycloakModelUtils.generateId());
         token.issuedNow();
@@ -489,13 +490,21 @@ public class AuthenticationManager {
         if (realm.getSsoSessionMaxLifespan() > 0) {
             token.expiration(Time.currentTime() + realm.getSsoSessionMaxLifespan());
         }
+
+        String stateChecker = (String) keycloakSession.getAttribute("state_checker");
+        if (stateChecker == null) {
+            stateChecker = Base64Url.encode(KeycloakModelUtils.generateSecret());
+            keycloakSession.setAttribute("state_checker", stateChecker);
+        }
+        token.getOtherClaims().put("state_checker", stateChecker);
+
         return token;
     }
 
     public static void createLoginCookie(KeycloakSession keycloakSession, RealmModel realm, UserModel user, UserSessionModel session, UriInfo uriInfo, ClientConnection connection) {
         String cookiePath = getIdentityCookiePath(realm, uriInfo);
         String issuer = Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName());
-        AccessToken identityToken = createIdentityToken(realm, user, session, issuer);
+        AccessToken identityToken = createIdentityToken(keycloakSession, realm, user, session, issuer);
         String encoded = encodeToken(keycloakSession, realm, identityToken);
         boolean secureOnly = realm.getSslRequired().isRequired(connection);
         int maxAge = NewCookie.DEFAULT_MAX_AGE;
@@ -1044,6 +1053,8 @@ public class AuthenticationManager {
                 return null;
             }
 
+            session.setAttribute("state_checker", token.getOtherClaims().get("state_checker"));
+
             return new AuthResult(user, userSession, token);
         } catch (VerificationException e) {
             logger.debugf("Failed to verify identity token: %s", e.getMessage());
diff --git a/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java b/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java
index bcc99b6..5d2eab5 100755
--- a/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java
@@ -58,8 +58,6 @@ import java.util.Set;
 public abstract class AbstractSecuredLocalService {
     private static final Logger logger = Logger.getLogger(AbstractSecuredLocalService.class);
 
-    private static final String KEYCLOAK_STATE_CHECKER = "KEYCLOAK_STATE_CHECKER";
-
     protected final ClientModel client;
     protected RealmModel realm;
 
@@ -127,55 +125,8 @@ public abstract class AbstractSecuredLocalService {
         }
     }
 
-    protected void updateCsrfChecks() {
-        stateChecker = getStateChecker();
-        if (stateChecker == null) {
-            stateChecker = Base64Url.encode(KeycloakModelUtils.generateSecret());
-
-            StringBuilder sb = new StringBuilder();
-            sb.append(auth.getSession().getId());
-            sb.append("/");
-            sb.append(stateChecker);
-
-            String sessionCookieValue = sb.toString();
-
-            String cookiePath = AuthenticationManager.getAccountCookiePath(realm, uriInfo);
-            boolean secureOnly = realm.getSslRequired().isRequired(clientConnection);
-            CookieHelper.addCookie(KEYCLOAK_STATE_CHECKER, sessionCookieValue, cookiePath, null, null, -1, secureOnly, true);
-        }
-    }
-
     protected abstract Set<String> getValidPaths();
 
-    /**
-     * Check to see if form post has sessionId hidden field and match it against the session id.
-     *
-     * @param formData
-     */
-    protected void csrfCheck(final MultivaluedMap<String, String> formData) {
-        String stateChecker = formData.getFirst("stateChecker");
-        if (stateChecker == null || !stateChecker.equals(getStateChecker())) {
-            throw new ForbiddenException();
-        }
-    }
-
-    protected String getStateChecker() {
-        Cookie cookie = headers.getCookies().get(KEYCLOAK_STATE_CHECKER);
-        if (cookie != null) {
-            stateChecker = cookie.getValue();
-            String[] s = stateChecker.split("/");
-            if (s.length == 2) {
-                String sessionId = s[0];
-                String stateChecker = s[1];
-
-                if (auth.getSession().getId().equals(sessionId)) {
-                    return stateChecker;
-                }
-            }
-        }
-        return null;
-    }
-
     protected abstract URI getBaseRedirectUri();
 
     protected Response login(String path) {
diff --git a/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java b/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java
index 3cfb6d3..06b3758 100755
--- a/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java
+++ b/services/src/main/java/org/keycloak/services/resources/account/AccountFormService.java
@@ -120,8 +120,8 @@ public class AccountFormService extends AbstractSecuredLocalService {
 
         AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm);
         if (authResult != null) {
+            stateChecker = (String) session.getAttribute("state_checker");
             auth = new Auth(realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), true);
-            updateCsrfChecks();
             account.setStateChecker(stateChecker);
         }
 
@@ -798,4 +798,12 @@ public class AccountFormService extends AbstractSecuredLocalService {
         }
     }
 
+    private void csrfCheck(final MultivaluedMap<String, String> formData) {
+        String formStateChecker = formData.getFirst("stateChecker");
+        if (formStateChecker == null || !formStateChecker.equals(this.stateChecker)) {
+            throw new ForbiddenException();
+        }
+    }
+
+
 }