keycloak-uncached

Merge pull request #684 from stianst/master Fix CRSF protection

9/10/2014 5:34:49 AM

Details

diff --git a/core/src/main/java/org/keycloak/util/UriUtils.java b/core/src/main/java/org/keycloak/util/UriUtils.java
new file mode 100644
index 0000000..873283f
--- /dev/null
+++ b/core/src/main/java/org/keycloak/util/UriUtils.java
@@ -0,0 +1,19 @@
+package org.keycloak.util;
+
+import java.net.URI;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class UriUtils {
+
+    public static String getOrigin(URI uri) {
+        return getOrigin(uri.toString());
+    }
+
+    public static String getOrigin(String uri) {
+        String u = uri.toString();
+        return u.substring(0, u.indexOf('/', 8));
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index 540f7ec..19e4e4c 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -64,6 +64,7 @@ import org.keycloak.services.validation.Validation;
 import org.keycloak.social.SocialLoader;
 import org.keycloak.social.SocialProvider;
 import org.keycloak.social.SocialProviderException;
+import org.keycloak.util.UriUtils;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
@@ -148,30 +149,38 @@ public class AccountService {
 
         account = session.getProvider(AccountProvider.class).setRealm(realm).setUriInfo(uriInfo);
 
-        AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, clientConnection, headers);
+        AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers);
         if (authResult != null) {
-            auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, authResult.getSession(), true);
-            Cookie cookie = headers.getCookies().get(KEYCLOAK_STATE_CHECKER);
-            if (cookie != null) {
-                stateChecker = cookie.getValue();
-            } else {
-                stateChecker = UUID.randomUUID().toString();
-                String cookiePath = AuthenticationManager.getRealmCookiePath(realm, uriInfo);
-                boolean secureOnly = realm.getSslRequired().isRequired(clientConnection);
-                CookieHelper.addCookie(KEYCLOAK_STATE_CHECKER, stateChecker, cookiePath, null, null, -1, secureOnly, true);
-            }
-            account.setStateChecker(stateChecker);
-
+            auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, authResult.getSession(), false);
         } else {
-            authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers);
+            authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, clientConnection, headers);
             if (authResult != null) {
-                auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, authResult.getSession(), false);
+                auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, authResult.getSession(), true);
+                Cookie cookie = headers.getCookies().get(KEYCLOAK_STATE_CHECKER);
+                if (cookie != null) {
+                    stateChecker = cookie.getValue();
+                } else {
+                    stateChecker = UUID.randomUUID().toString();
+                    String cookiePath = AuthenticationManager.getRealmCookiePath(realm, uriInfo);
+                    boolean secureOnly = realm.getSslRequired().isRequired(clientConnection);
+                    CookieHelper.addCookie(KEYCLOAK_STATE_CHECKER, stateChecker, cookiePath, null, null, -1, secureOnly, true);
+                }
+                account.setStateChecker(stateChecker);
             }
         }
+
+        String requestOrigin = UriUtils.getOrigin(uriInfo.getBaseUri());
+
         // don't allow cors requests unless they were authenticated by an access token
         // This is to prevent CSRF attacks.
         if (auth != null && auth.isCookieAuthenticated()) {
-            if (headers.getRequestHeaders().containsKey("Origin")) {
+            String origin = headers.getRequestHeaders().getFirst("Origin");
+            if (origin != null && !requestOrigin.equals(origin)) {
+                throw new ForbiddenException();
+            }
+
+            String referrer = headers.getRequestHeaders().getFirst("Referer");
+            if (referrer != null && !requestOrigin.equals(UriUtils.getOrigin(referrer))) {
                 throw new ForbiddenException();
             }
         }