keycloak-aplcache

more

6/4/2015 11:18:24 AM

Details

diff --git a/distribution/subsystem-war/src/main/webapp/WEB-INF/web.xml b/distribution/subsystem-war/src/main/webapp/WEB-INF/web.xml
index 7228afe..4257449 100755
--- a/distribution/subsystem-war/src/main/webapp/WEB-INF/web.xml
+++ b/distribution/subsystem-war/src/main/webapp/WEB-INF/web.xml
@@ -26,11 +26,6 @@
     </listener>
 
     <filter>
-        <filter-name>Keycloak Client Connection Filter</filter-name>
-        <filter-class>org.keycloak.services.filters.ClientConnectionFilter</filter-class>
-    </filter>
-
-    <filter>
         <filter-name>Keycloak Session Management</filter-name>
         <filter-class>org.keycloak.services.filters.KeycloakSessionServletFilter</filter-class>
     </filter>
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakContext.java b/model/api/src/main/java/org/keycloak/models/KeycloakContext.java
old mode 100644
new mode 100755
index ac13d3f..4d33403
--- a/model/api/src/main/java/org/keycloak/models/KeycloakContext.java
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakContext.java
@@ -1,5 +1,7 @@
 package org.keycloak.models;
 
+import org.keycloak.ClientConnection;
+
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.UriInfo;
 
@@ -20,4 +22,8 @@ public interface KeycloakContext {
 
     void setClient(ClientModel client);
 
+    ClientConnection getConnection();
+
+    void setConnection(ClientConnection connection);
+
 }
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
index c27fb1e..bf97994 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
@@ -434,7 +434,7 @@ public class AuthenticationProcessor {
             if (authenticator.requiresUser() && authUser != null) {
                 configuredFor = authenticator.configuredFor(session, realm, authUser);
                 if (!configuredFor) {
-                    if (model.getRequirement() == AuthenticationExecutionModel.Requirement.REQUIRED) {
+                    if (model.isRequired()) {
                         if (model.isUserSetupAllowed()) {
                             clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SETUP_REQUIRED);
                             String requiredAction = authenticator.getRequiredAction();
@@ -445,6 +445,9 @@ public class AuthenticationProcessor {
                         } else {
                             throw new AuthException(Error.CREDENTIAL_SETUP_REQUIRED);
                         }
+                    } else if (model.isOptional()) {
+                        clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SKIPPED);
+                        continue;
                     }
                 }
             }
@@ -477,7 +480,9 @@ public class AuthenticationProcessor {
                 clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.CHALLENGED);
                 return context.challenge;
             } else if (result == Status.ATTEMPTED) {
-                if (model.getRequirement() == AuthenticationExecutionModel.Requirement.REQUIRED) throw new AuthException(Error.INVALID_CREDENTIALS);
+                if (model.getRequirement() == AuthenticationExecutionModel.Requirement.REQUIRED) {
+                    throw new AuthException(Error.INVALID_CREDENTIALS);
+                }
                 clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.ATTEMPTED);
                 continue;
             } else {
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakContext.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakContext.java
old mode 100644
new mode 100755
index 1b0e567..99849a9
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakContext.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakContext.java
@@ -1,6 +1,7 @@
 package org.keycloak.services;
 
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.ClientConnection;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakContext;
 import org.keycloak.models.RealmModel;
@@ -17,6 +18,8 @@ public class DefaultKeycloakContext implements KeycloakContext {
 
     private ClientModel client;
 
+    private ClientConnection connection;
+
     @Override
     public UriInfo getUri() {
         return ResteasyProviderFactory.getContextData(UriInfo.class);
@@ -47,4 +50,13 @@ public class DefaultKeycloakContext implements KeycloakContext {
         this.client = client;
     }
 
+    @Override
+    public ClientConnection getConnection() {
+        return connection;
+    }
+
+    @Override
+    public void setConnection(ClientConnection connection) {
+        this.connection = connection;
+    }
 }
diff --git a/services/src/main/java/org/keycloak/services/filters/ClientConnectionFilter.java b/services/src/main/java/org/keycloak/services/filters/ClientConnectionFilter.java
index f172d39..e412c0d 100755
--- a/services/src/main/java/org/keycloak/services/filters/ClientConnectionFilter.java
+++ b/services/src/main/java/org/keycloak/services/filters/ClientConnectionFilter.java
@@ -15,6 +15,7 @@ import java.io.IOException;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
+@Deprecated
 public class ClientConnectionFilter implements Filter {
     @Override
     public void init(FilterConfig filterConfig) throws ServletException {
diff --git a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
index 4115567..cfd482e 100755
--- a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
+++ b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
@@ -1,6 +1,7 @@
 package org.keycloak.services.filters;
 
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.ClientConnection;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.KeycloakTransaction;
@@ -26,11 +27,29 @@ public class KeycloakSessionServletFilter implements Filter {
 
     @Override
     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
-        HttpServletRequest request = (HttpServletRequest)servletRequest;
+        final HttpServletRequest request = (HttpServletRequest)servletRequest;
 
         KeycloakSessionFactory sessionFactory = (KeycloakSessionFactory) servletRequest.getServletContext().getAttribute(KeycloakSessionFactory.class.getName());
         KeycloakSession session = sessionFactory.create();
         ResteasyProviderFactory.pushContext(KeycloakSession.class, session);
+        ClientConnection connection = new ClientConnection() {
+            @Override
+            public String getRemoteAddr() {
+                return request.getRemoteAddr();
+            }
+
+            @Override
+            public String getRemoteHost() {
+                return request.getRemoteHost();
+            }
+
+            @Override
+            public int getReportPort() {
+                return request.getRemotePort();
+            }
+        };
+        session.getContext().setConnection(connection);
+        ResteasyProviderFactory.pushContext(ClientConnection.class, connection);
 
         KeycloakTransaction tx = session.getTransaction();
         ResteasyProviderFactory.pushContext(KeycloakTransaction.class, tx);
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 9221268..a1da985 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -315,6 +315,8 @@ public class LoginActionsService {
             event.error(Errors.CLIENT_NOT_FOUND);
             return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
         }
+        session.getContext().setClient(client);
+
         if (!client.isEnabled()) {
             event.error(Errors.CLIENT_NOT_FOUND);
             return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthGrantTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthGrantTest.java
index 939231f..1e00be8 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthGrantTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthGrantTest.java
@@ -1,267 +1,267 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2012, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.keycloak.testsuite.oauth;
-
-import org.junit.Assert;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.constants.KerberosConstants;
-import org.keycloak.events.Details;
-import org.keycloak.events.Event;
-import org.keycloak.events.EventType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.protocol.oidc.OIDCLoginProtocolFactory;
-import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.testsuite.AssertEvents;
-import org.keycloak.testsuite.OAuthClient;
-import org.keycloak.testsuite.pages.AccountApplicationsPage;
-import org.keycloak.testsuite.pages.AppPage;
-import org.keycloak.testsuite.pages.LoginPage;
-import org.keycloak.testsuite.pages.OAuthGrantPage;
-import org.keycloak.testsuite.rule.KeycloakRule;
-import org.keycloak.testsuite.rule.WebResource;
-import org.keycloak.testsuite.rule.WebRule;
-import org.openqa.selenium.WebDriver;
-
-import java.io.IOException;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
- */
-public class OAuthGrantTest {
-
-    @ClassRule
-    public static KeycloakRule keycloakRule = new KeycloakRule();
-
-    @Rule
-    public AssertEvents events = new AssertEvents(keycloakRule);
-
-    @Rule
-    public WebRule webRule = new WebRule(this);
-
-    @WebResource
-    protected WebDriver driver;
-
-    @WebResource
-    protected OAuthClient oauth;
-
-    @WebResource
-    protected LoginPage loginPage;
-
-    @WebResource
-    protected OAuthGrantPage grantPage;
-
-    @WebResource
-    protected AccountApplicationsPage accountAppsPage;
-
-    @WebResource
-    protected AppPage appPage;
-
-    private static String ROLE_USER = "Have User privileges";
-    private static String ROLE_CUSTOMER = "Have Customer User privileges";
-
-    @Test
-    public void oauthGrantAcceptTest() {
-        oauth.clientId("third-party");
-        oauth.doLoginGrant("test-user@localhost", "password");
-
-        grantPage.assertCurrent();
-        Assert.assertTrue(driver.getPageSource().contains(ROLE_USER));
-        Assert.assertTrue(driver.getPageSource().contains(ROLE_CUSTOMER));
-
-        grantPage.accept();
-
-        Assert.assertTrue(oauth.getCurrentQuery().containsKey(OAuth2Constants.CODE));
-
-        Event loginEvent = events.expectLogin().client("third-party").assertEvent();
-        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
-        String sessionId = loginEvent.getSessionId();
-
-        OAuthClient.AccessTokenResponse accessToken = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get(OAuth2Constants.CODE), "password");
-
-        String tokenString = accessToken.getAccessToken();
-        Assert.assertNotNull(tokenString);
-        AccessToken token = oauth.verifyToken(tokenString);
-        assertEquals(sessionId, token.getSessionState());
-
-        AccessToken.Access realmAccess = token.getRealmAccess();
-        assertEquals(1, realmAccess.getRoles().size());
-        Assert.assertTrue(realmAccess.isUserInRole("user"));
-
-        Map<String,AccessToken.Access> resourceAccess = token.getResourceAccess();
-        assertEquals(1, resourceAccess.size());
-        assertEquals(1, resourceAccess.get("test-app").getRoles().size());
-        Assert.assertTrue(resourceAccess.get("test-app").isUserInRole("customer-user"));
-
-        events.expectCodeToToken(codeId, loginEvent.getSessionId()).client("third-party").assertEvent();
-
-        accountAppsPage.open();
-        accountAppsPage.revokeGrant("third-party");
-
-        events.expect(EventType.REVOKE_GRANT)
-                .client("account").detail(Details.REVOKED_CLIENT, "third-party").assertEvent();
-    }
-
-    @Test
-    public void oauthGrantCancelTest() {
-        oauth.clientId("third-party");
-        oauth.doLoginGrant("test-user@localhost", "password");
-
-        grantPage.assertCurrent();
-        Assert.assertTrue(driver.getPageSource().contains(ROLE_USER));
-        Assert.assertTrue(driver.getPageSource().contains(ROLE_CUSTOMER));
-
-        grantPage.cancel();
-
-        Assert.assertTrue(oauth.getCurrentQuery().containsKey(OAuth2Constants.ERROR));
-        assertEquals("access_denied", oauth.getCurrentQuery().get(OAuth2Constants.ERROR));
-
-        events.expectLogin().client("third-party").error("rejected_by_user").assertEvent();
-    }
-
-    @Test
-    public void oauthGrantNotShownWhenAlreadyGranted() {
-        // Grant permissions on grant screen
-        oauth.clientId("third-party");
-        oauth.doLoginGrant("test-user@localhost", "password");
-
-        grantPage.assertCurrent();
-        grantPage.accept();
-
-        events.expectLogin().client("third-party").assertEvent();
-
-        // Assert permissions granted on Account mgmt. applications page
-        accountAppsPage.open();
-        AccountApplicationsPage.AppEntry thirdPartyEntry = accountAppsPage.getApplications().get("third-party");
-        Assert.assertTrue(thirdPartyEntry.getRolesGranted().contains(ROLE_USER));
-        Assert.assertTrue(thirdPartyEntry.getRolesGranted().contains("Have Customer User privileges in test-app"));
-        Assert.assertTrue(thirdPartyEntry.getProtocolMappersGranted().contains("Full name"));
-        Assert.assertTrue(thirdPartyEntry.getProtocolMappersGranted().contains("Email"));
-
-        // Open login form and assert grantPage not shown
-        oauth.openLoginForm();
-        appPage.assertCurrent();
-        events.expectLogin().detail(Details.AUTH_METHOD, "sso").removeDetail(Details.USERNAME).client("third-party").assertEvent();
-
-        // Revoke grant in account mgmt.
-        accountAppsPage.open();
-        accountAppsPage.revokeGrant("third-party");
-
-        events.expect(EventType.REVOKE_GRANT)
-                .client("account").detail(Details.REVOKED_CLIENT, "third-party").assertEvent();
-
-        // Open login form again and assert grant Page is shown
-        oauth.openLoginForm();
-        grantPage.assertCurrent();
-        Assert.assertTrue(driver.getPageSource().contains(ROLE_USER));
-        Assert.assertTrue(driver.getPageSource().contains(ROLE_CUSTOMER));
-    }
-
-    @Test
-    public void oauthGrantAddAnotherRoleAndMapper() {
-        // Grant permissions on grant screen
-        oauth.clientId("third-party");
-        oauth.doLoginGrant("test-user@localhost", "password");
-
-        // Add new protocolMapper and role before showing grant page
-        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
-
-            @Override
-            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                ProtocolMapperModel protocolMapper = UserSessionNoteMapper.createClaimMapper(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME,
-                        KerberosConstants.GSS_DELEGATION_CREDENTIAL,
-                        KerberosConstants.GSS_DELEGATION_CREDENTIAL, "String",
-                        true, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME,
-                        true, false);
-
-                ClientModel thirdPartyApp = appRealm.getClientByClientId("third-party");
-                thirdPartyApp.addProtocolMapper(protocolMapper);
-
-                RoleModel newRole = appRealm.addRole("new-role");
-                thirdPartyApp.addScopeMapping(newRole);
-                UserModel testUser = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm);
-                testUser.grantRole(newRole);
-            }
-
-        });
-
-        // Confirm grant page
-        grantPage.assertCurrent();
-        grantPage.accept();
-        events.expectLogin().client("third-party").assertEvent();
-
-        // Assert new role and protocol mapper not in account mgmt.
-        accountAppsPage.open();
-        AccountApplicationsPage.AppEntry appEntry = accountAppsPage.getApplications().get("third-party");
-        Assert.assertFalse(appEntry.getRolesGranted().contains("new-role"));
-        Assert.assertFalse(appEntry.getProtocolMappersGranted().contains(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME));
-
-        // Show grant page another time. Just new role and protocol mapper are on the page
-        oauth.openLoginForm();
-        grantPage.assertCurrent();
-        Assert.assertFalse(driver.getPageSource().contains(ROLE_USER));
-        Assert.assertFalse(driver.getPageSource().contains("Full name"));
-        Assert.assertTrue(driver.getPageSource().contains("new-role"));
-        Assert.assertTrue(driver.getPageSource().contains(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME));
-        grantPage.accept();
-        events.expectLogin().client("third-party").assertEvent();
-
-        // Go to account mgmt. Everything is granted now
-        accountAppsPage.open();
-        appEntry = accountAppsPage.getApplications().get("third-party");
-        Assert.assertTrue(appEntry.getRolesGranted().contains("new-role"));
-        Assert.assertTrue(appEntry.getProtocolMappersGranted().contains(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME));
-
-        // Revoke
-        accountAppsPage.revokeGrant("third-party");
-        events.expect(EventType.REVOKE_GRANT)
-                .client("account").detail(Details.REVOKED_CLIENT, "third-party").assertEvent();
-
-        // Cleanup
-        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
-
-            @Override
-            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                ClientModel thirdPartyApp = appRealm.getClientByClientId("third-party");
-                ProtocolMapperModel gssMapper = thirdPartyApp.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME);
-                thirdPartyApp.removeProtocolMapper(gssMapper);
-
-                RoleModel newRole = appRealm.getRole("new-role");
-                appRealm.removeRole(newRole);
-            }
-
-        });
-    }
-
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite.oauth;
+
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.constants.KerberosConstants;
+import org.keycloak.events.Details;
+import org.keycloak.events.Event;
+import org.keycloak.events.EventType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolFactory;
+import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.AssertEvents;
+import org.keycloak.testsuite.OAuthClient;
+import org.keycloak.testsuite.pages.AccountApplicationsPage;
+import org.keycloak.testsuite.pages.AppPage;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.pages.OAuthGrantPage;
+import org.keycloak.testsuite.rule.KeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+import org.openqa.selenium.WebDriver;
+
+import java.io.IOException;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
+ */
+public class OAuthGrantTest {
+
+    @ClassRule
+    public static KeycloakRule keycloakRule = new KeycloakRule();
+
+    @Rule
+    public AssertEvents events = new AssertEvents(keycloakRule);
+
+    @Rule
+    public WebRule webRule = new WebRule(this);
+
+    @WebResource
+    protected WebDriver driver;
+
+    @WebResource
+    protected OAuthClient oauth;
+
+    @WebResource
+    protected LoginPage loginPage;
+
+    @WebResource
+    protected OAuthGrantPage grantPage;
+
+    @WebResource
+    protected AccountApplicationsPage accountAppsPage;
+
+    @WebResource
+    protected AppPage appPage;
+
+    private static String ROLE_USER = "Have User privileges";
+    private static String ROLE_CUSTOMER = "Have Customer User privileges";
+
+    @Test
+    public void oauthGrantAcceptTest() {
+        oauth.clientId("third-party");
+        oauth.doLoginGrant("test-user@localhost", "password");
+
+        grantPage.assertCurrent();
+        Assert.assertTrue(driver.getPageSource().contains(ROLE_USER));
+        Assert.assertTrue(driver.getPageSource().contains(ROLE_CUSTOMER));
+
+        grantPage.accept();
+
+        Assert.assertTrue(oauth.getCurrentQuery().containsKey(OAuth2Constants.CODE));
+
+        Event loginEvent = events.expectLogin().client("third-party").assertEvent();
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+        String sessionId = loginEvent.getSessionId();
+
+        OAuthClient.AccessTokenResponse accessToken = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get(OAuth2Constants.CODE), "password");
+
+        String tokenString = accessToken.getAccessToken();
+        Assert.assertNotNull(tokenString);
+        AccessToken token = oauth.verifyToken(tokenString);
+        assertEquals(sessionId, token.getSessionState());
+
+        AccessToken.Access realmAccess = token.getRealmAccess();
+        assertEquals(1, realmAccess.getRoles().size());
+        Assert.assertTrue(realmAccess.isUserInRole("user"));
+
+        Map<String,AccessToken.Access> resourceAccess = token.getResourceAccess();
+        assertEquals(1, resourceAccess.size());
+        assertEquals(1, resourceAccess.get("test-app").getRoles().size());
+        Assert.assertTrue(resourceAccess.get("test-app").isUserInRole("customer-user"));
+
+        events.expectCodeToToken(codeId, loginEvent.getSessionId()).client("third-party").assertEvent();
+
+        accountAppsPage.open();
+        accountAppsPage.revokeGrant("third-party");
+
+        events.expect(EventType.REVOKE_GRANT)
+                .client("account").detail(Details.REVOKED_CLIENT, "third-party").assertEvent();
+    }
+
+    @Test
+    public void oauthGrantCancelTest() {
+        oauth.clientId("third-party");
+        oauth.doLoginGrant("test-user@localhost", "password");
+
+        grantPage.assertCurrent();
+        Assert.assertTrue(driver.getPageSource().contains(ROLE_USER));
+        Assert.assertTrue(driver.getPageSource().contains(ROLE_CUSTOMER));
+
+        grantPage.cancel();
+
+        Assert.assertTrue(oauth.getCurrentQuery().containsKey(OAuth2Constants.ERROR));
+        assertEquals("access_denied", oauth.getCurrentQuery().get(OAuth2Constants.ERROR));
+
+        events.expectLogin().client("third-party").error("rejected_by_user").assertEvent();
+    }
+
+    @Test
+    public void oauthGrantNotShownWhenAlreadyGranted() {
+        // Grant permissions on grant screen
+        oauth.clientId("third-party");
+        oauth.doLoginGrant("test-user@localhost", "password");
+
+        grantPage.assertCurrent();
+        grantPage.accept();
+
+        events.expectLogin().client("third-party").assertEvent();
+
+        // Assert permissions granted on Account mgmt. applications page
+        accountAppsPage.open();
+        AccountApplicationsPage.AppEntry thirdPartyEntry = accountAppsPage.getApplications().get("third-party");
+        Assert.assertTrue(thirdPartyEntry.getRolesGranted().contains(ROLE_USER));
+        Assert.assertTrue(thirdPartyEntry.getRolesGranted().contains("Have Customer User privileges in test-app"));
+        Assert.assertTrue(thirdPartyEntry.getProtocolMappersGranted().contains("Full name"));
+        Assert.assertTrue(thirdPartyEntry.getProtocolMappersGranted().contains("Email"));
+
+        // Open login form and assert grantPage not shown
+        oauth.openLoginForm();
+        appPage.assertCurrent();
+        events.expectLogin().removeDetail(Details.USERNAME).client("third-party").assertEvent();
+
+        // Revoke grant in account mgmt.
+        accountAppsPage.open();
+        accountAppsPage.revokeGrant("third-party");
+
+        events.expect(EventType.REVOKE_GRANT)
+                .client("account").detail(Details.REVOKED_CLIENT, "third-party").assertEvent();
+
+        // Open login form again and assert grant Page is shown
+        oauth.openLoginForm();
+        grantPage.assertCurrent();
+        Assert.assertTrue(driver.getPageSource().contains(ROLE_USER));
+        Assert.assertTrue(driver.getPageSource().contains(ROLE_CUSTOMER));
+    }
+
+    @Test
+    public void oauthGrantAddAnotherRoleAndMapper() {
+        // Grant permissions on grant screen
+        oauth.clientId("third-party");
+        oauth.doLoginGrant("test-user@localhost", "password");
+
+        // Add new protocolMapper and role before showing grant page
+        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                ProtocolMapperModel protocolMapper = UserSessionNoteMapper.createClaimMapper(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME,
+                        KerberosConstants.GSS_DELEGATION_CREDENTIAL,
+                        KerberosConstants.GSS_DELEGATION_CREDENTIAL, "String",
+                        true, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME,
+                        true, false);
+
+                ClientModel thirdPartyApp = appRealm.getClientByClientId("third-party");
+                thirdPartyApp.addProtocolMapper(protocolMapper);
+
+                RoleModel newRole = appRealm.addRole("new-role");
+                thirdPartyApp.addScopeMapping(newRole);
+                UserModel testUser = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm);
+                testUser.grantRole(newRole);
+            }
+
+        });
+
+        // Confirm grant page
+        grantPage.assertCurrent();
+        grantPage.accept();
+        events.expectLogin().client("third-party").assertEvent();
+
+        // Assert new role and protocol mapper not in account mgmt.
+        accountAppsPage.open();
+        AccountApplicationsPage.AppEntry appEntry = accountAppsPage.getApplications().get("third-party");
+        Assert.assertFalse(appEntry.getRolesGranted().contains("new-role"));
+        Assert.assertFalse(appEntry.getProtocolMappersGranted().contains(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME));
+
+        // Show grant page another time. Just new role and protocol mapper are on the page
+        oauth.openLoginForm();
+        grantPage.assertCurrent();
+        Assert.assertFalse(driver.getPageSource().contains(ROLE_USER));
+        Assert.assertFalse(driver.getPageSource().contains("Full name"));
+        Assert.assertTrue(driver.getPageSource().contains("new-role"));
+        Assert.assertTrue(driver.getPageSource().contains(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME));
+        grantPage.accept();
+        events.expectLogin().client("third-party").assertEvent();
+
+        // Go to account mgmt. Everything is granted now
+        accountAppsPage.open();
+        appEntry = accountAppsPage.getApplications().get("third-party");
+        Assert.assertTrue(appEntry.getRolesGranted().contains("new-role"));
+        Assert.assertTrue(appEntry.getProtocolMappersGranted().contains(KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME));
+
+        // Revoke
+        accountAppsPage.revokeGrant("third-party");
+        events.expect(EventType.REVOKE_GRANT)
+                .client("account").detail(Details.REVOKED_CLIENT, "third-party").assertEvent();
+
+        // Cleanup
+        keycloakRule.update(new KeycloakRule.KeycloakSetup() {
+
+            @Override
+            public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+                ClientModel thirdPartyApp = appRealm.getClientByClientId("third-party");
+                ProtocolMapperModel gssMapper = thirdPartyApp.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME);
+                thirdPartyApp.removeProtocolMapper(gssMapper);
+
+                RoleModel newRole = appRealm.getRole("new-role");
+                appRealm.removeRole(newRole);
+            }
+
+        });
+    }
+
+}