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 7228afe95f..4257449a98 100755
--- a/distribution/subsystem-war/src/main/webapp/WEB-INF/web.xml
+++ b/distribution/subsystem-war/src/main/webapp/WEB-INF/web.xml
@@ -25,11 +25,6 @@
org.keycloak.services.listeners.KeycloakSessionDestroyListener
-
- Keycloak Client Connection Filter
- org.keycloak.services.filters.ClientConnectionFilter
-
-
Keycloak Session Management
org.keycloak.services.filters.KeycloakSessionServletFilter
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 ac13d3fbcc..4d33403586
--- 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 c27fb1efa4..bf97994876 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 1b0e567def..99849a90db
--- 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 f172d39123..e412c0d9c1 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 Bill Burke
* @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 411556784f..cfd482e3a9 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 9221268e8a..a1da98545f 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 939231f031..1e00be8ab6 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 Viliam Rockai
- */
-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 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 Viliam Rockai
+ */
+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 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);
+ }
+
+ });
+ }
+
+}