keycloak-uncached

Merge pull request #2731 from abstractj/RHSSO-130-1.9.x RHSSO-130:

4/25/2016 8:43:05 AM

Details

diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
index 1450901..5f54c07 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
@@ -88,8 +88,8 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc
     }
 
     @Override
-    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                            UserSessionModel userSession, ClientSessionModel clientSession) {
+    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session2,
+                                            UserSessionModel userSession2, ClientSessionModel clientSessio2n) {
         String role = mappingModel.getConfig().get(ROLE_CONFIG);
         String newName = mappingModel.getConfig().get(NEW_ROLE_NAME);
 
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java
index 75c01da..e294879 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java
@@ -655,4 +655,4 @@ public class OAuthClient {
         return publicKeys.get(realm);
     }
 
-}
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ApiUtil.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ApiUtil.java
index a60926e..aae4f53 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ApiUtil.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ApiUtil.java
@@ -99,6 +99,10 @@ public class ApiUtil {
         return user;
     }
 
+    public static UserResource findUserByUsernameId(RealmResource realm, String username) {
+        return realm.users().get(findUserByUsername(realm, username).getId());
+    }
+
     public static String createUserWithAdminClient(RealmResource realm, UserRepresentation user) {
         Response response = realm.users().create(user);
         String createdId = getCreatedId(response);
@@ -158,5 +162,4 @@ public class ApiUtil {
         }
         return contains;
     }
-
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
new file mode 100755
index 0000000..6e684ef
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
@@ -0,0 +1,1058 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.oauth;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.admin.client.resource.ClientTemplateResource;
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.admin.client.resource.UserResource;
+import org.keycloak.common.enums.SslRequired;
+import org.keycloak.common.util.Time;
+import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.jose.jws.JWSInputException;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
+import org.keycloak.protocol.oidc.mappers.HardcodedClaim;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.ClientTemplateRepresentation;
+import org.keycloak.representations.idm.EventRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.testsuite.AbstractKeycloakTest;
+import org.keycloak.testsuite.AssertEvents;
+import org.keycloak.testsuite.util.ClientBuilder;
+import org.keycloak.testsuite.util.OAuthClient;
+import org.keycloak.testsuite.util.RealmManager;
+import org.keycloak.testsuite.util.RoleBuilder;
+import org.keycloak.testsuite.util.UserBuilder;
+import org.keycloak.testsuite.util.UserManager;
+import org.keycloak.util.BasicAuthHelper;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.lessThanOrEqualTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
+import static org.keycloak.testsuite.admin.ApiUtil.findClientByClientId;
+import static org.keycloak.testsuite.admin.ApiUtil.findClientResourceByClientId;
+import static org.keycloak.testsuite.admin.ApiUtil.findUserByUsername;
+import static org.keycloak.testsuite.admin.ApiUtil.findUserByUsernameId;
+import static org.keycloak.testsuite.util.OAuthClient.AUTH_SERVER_ROOT;
+import static org.keycloak.testsuite.util.ProtocolMapperUtil.createAddressMapper;
+import static org.keycloak.testsuite.util.ProtocolMapperUtil.createClaimMapper;
+import static org.keycloak.testsuite.util.ProtocolMapperUtil.createHardcodedClaim;
+import static org.keycloak.testsuite.util.ProtocolMapperUtil.createHardcodedRole;
+import static org.keycloak.testsuite.util.ProtocolMapperUtil.createRoleNameMapper;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class AccessTokenTest extends AbstractKeycloakTest {
+
+    @Rule
+    public AssertEvents events = new AssertEvents(this);
+
+
+    @Override
+    public void beforeAbstractKeycloakTest() throws Exception {
+        super.beforeAbstractKeycloakTest();
+    }
+
+    @Before
+    public void clientConfiguration() {
+        ClientResource clientResource = findClientByClientId(adminClient.realm("test"), "test-app");
+        ClientRepresentation clientRepresentation = new ClientRepresentation();
+        clientRepresentation.setDirectAccessGrantsEnabled(true);
+        clientResource.update(clientRepresentation);
+
+        /*
+         * Configure the default client ID. Seems like OAuthClient is keeping the state of clientID
+         * For example: If some test case configure oauth.clientId("sample-public-client"), other tests
+         * will faile and the clientID will always be "sample-public-client
+         * @see AccessTokenTest#testAuthorizationNegotiateHeaderIgnored()
+         */
+        oauth.clientId("test-app");
+    }
+
+    @Override
+    public void addTestRealms(List<RealmRepresentation> testRealms) {
+
+        RealmRepresentation realm = loadJson(getClass().getResourceAsStream("/testrealm.json"), RealmRepresentation.class);
+
+        UserBuilder user = UserBuilder.create()
+                .id(KeycloakModelUtils.generateId())
+                .username("no-permissions")
+                .role("user")
+                .password("password");
+        realm.getUsers().add(user.build());
+
+        testRealms.add(realm);
+
+    }
+
+    @Test
+    public void accessTokenRequest() throws Exception {
+        oauth.doLogin("test-user@localhost", "password");
+
+        EventRepresentation loginEvent = events.expectLogin().assertEvent();
+
+        String sessionId = loginEvent.getSessionId();
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+
+        assertEquals(200, response.getStatusCode());
+
+        Assert.assertThat(response.getExpiresIn(), allOf(greaterThanOrEqualTo(250), lessThanOrEqualTo(300)));
+        Assert.assertThat(response.getRefreshExpiresIn(), allOf(greaterThanOrEqualTo(1750), lessThanOrEqualTo(1800)));
+
+        assertEquals("bearer", response.getTokenType());
+
+        AccessToken token = oauth.verifyToken(response.getAccessToken());
+
+        assertEquals(findUserByUsername(adminClient.realm("test"), "test-user@localhost").getId(), token.getSubject());
+        Assert.assertNotEquals("test-user@localhost", token.getSubject());
+
+        assertEquals(sessionId, token.getSessionState());
+
+        assertEquals(1, token.getRealmAccess().getRoles().size());
+        assertTrue(token.getRealmAccess().isUserInRole("user"));
+
+        assertEquals(1, token.getResourceAccess(oauth.getClientId()).getRoles().size());
+        assertTrue(token.getResourceAccess(oauth.getClientId()).isUserInRole("customer-user"));
+
+        EventRepresentation event = events.expectCodeToToken(codeId, sessionId).assertEvent();
+        assertEquals(token.getId(), event.getDetails().get(Details.TOKEN_ID));
+        assertEquals(oauth.verifyRefreshToken(response.getRefreshToken()).getId(), event.getDetails().get(Details.REFRESH_TOKEN_ID));
+        assertEquals(sessionId, token.getSessionState());
+
+    }
+
+    @Test
+    public void accessTokenInvalidClientCredentials() throws Exception {
+        oauth.doLogin("test-user@localhost", "password");
+
+        EventRepresentation loginEvent = events.expectLogin().assertEvent();
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "invalid");
+        assertEquals(400, response.getStatusCode());
+
+        AssertEvents.ExpectedEvent expectedEvent = events.expectCodeToToken(codeId, loginEvent.getSessionId()).error("invalid_client_credentials").clearDetails().user((String) null).session((String) null);
+        expectedEvent.assertEvent();
+    }
+
+    @Test
+    public void accessTokenMissingClientCredentials() throws Exception {
+        oauth.doLogin("test-user@localhost", "password");
+
+        EventRepresentation loginEvent = events.expectLogin().assertEvent();
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null);
+        assertEquals(400, response.getStatusCode());
+
+        AssertEvents.ExpectedEvent expectedEvent = events.expectCodeToToken(codeId, loginEvent.getSessionId()).error("invalid_client_credentials").clearDetails().user((String) null).session((String) null);
+        expectedEvent.assertEvent();
+    }
+
+    @Test
+    public void accessTokenInvalidRedirectUri() throws Exception {
+        oauth.doLogin("test-user@localhost", "password");
+
+        EventRepresentation loginEvent = events.expectLogin().assertEvent();
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+
+        //@TODO This new and was necesssary to not mess up with other tests cases
+        String redirectUri = oauth.getRedirectUri();
+
+        oauth.redirectUri("http://invalid");
+
+        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+        assertEquals(400, response.getStatusCode());
+        assertEquals("invalid_grant", response.getError());
+        assertEquals("Incorrect redirect_uri", response.getErrorDescription());
+
+        events.expectCodeToToken(codeId, loginEvent.getSessionId()).error("invalid_code")
+                .removeDetail(Details.TOKEN_ID)
+                .removeDetail(Details.REFRESH_TOKEN_ID)
+                .removeDetail(Details.REFRESH_TOKEN_TYPE)
+                .assertEvent();
+
+        //@TODO Reset back to the original URI. Maybe we should have something to reset to the original state at OAuthClient
+        oauth.redirectUri(redirectUri);
+
+    }
+
+    @Test
+    public void accessTokenUserSessionExpired() {
+        oauth.doLogin("test-user@localhost", "password");
+
+        EventRepresentation loginEvent = events.expectLogin().assertEvent();
+
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+        String sessionId = loginEvent.getSessionId();
+
+
+        testingClient.testing().removeUserSession("test", sessionId);
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+
+        OAuthClient.AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(code, "password");
+        assertEquals(400, tokenResponse.getStatusCode());
+        assertNull(tokenResponse.getAccessToken());
+        assertNull(tokenResponse.getRefreshToken());
+
+        events.expectCodeToToken(codeId, sessionId)
+                .removeDetail(Details.TOKEN_ID)
+                .user((String) null)
+                .session((String) null)
+                .removeDetail(Details.REFRESH_TOKEN_ID)
+                .removeDetail(Details.REFRESH_TOKEN_TYPE)
+                .error(Errors.INVALID_CODE).assertEvent();
+
+        events.clear();
+    }
+
+    @Test
+    public void accessTokenCodeExpired() {
+        RealmManager.realm(adminClient.realm("test")).accessCodeLifeSpan(1);
+        oauth.doLogin("test-user@localhost", "password");
+
+        EventRepresentation loginEvent = events.expectLogin().assertEvent();
+
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+        loginEvent.getSessionId();
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+
+        Time.setOffset(2);
+
+        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+        Assert.assertEquals(400, response.getStatusCode());
+
+        AssertEvents.ExpectedEvent expectedEvent = events.expectCodeToToken(codeId, null);
+        expectedEvent.error("invalid_code")
+                .removeDetail(Details.TOKEN_ID)
+                .removeDetail(Details.REFRESH_TOKEN_ID)
+                .removeDetail(Details.REFRESH_TOKEN_TYPE)
+                .user((String) null);
+        expectedEvent.assertEvent();
+
+        events.clear();
+
+        RealmManager.realm(adminClient.realm("test")).accessCodeLifeSpan(60);
+
+        Time.setOffset(0);
+    }
+
+    @Test
+    public void accessTokenCodeUsed() {
+        oauth.doLogin("test-user@localhost", "password");
+
+        EventRepresentation loginEvent = events.expectLogin().assertEvent();
+
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+        loginEvent.getSessionId();
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+        Assert.assertEquals(200, response.getStatusCode());
+
+        events.clear();
+
+        response = oauth.doAccessTokenRequest(code, "password");
+        Assert.assertEquals(400, response.getStatusCode());
+
+        AssertEvents.ExpectedEvent expectedEvent = events.expectCodeToToken(codeId, null);
+        expectedEvent.error("invalid_code")
+                .removeDetail(Details.TOKEN_ID)
+                .removeDetail(Details.REFRESH_TOKEN_ID)
+                .removeDetail(Details.REFRESH_TOKEN_TYPE)
+                .user((String) null);
+        expectedEvent.assertEvent();
+
+        events.clear();
+
+        RealmManager.realm(adminClient.realm("test")).accessCodeLifeSpan(60);
+    }
+
+    @Test
+    public void accessTokenCodeRoleMissing() {
+        RealmResource realmResource = adminClient.realm("test");
+        RoleRepresentation role = RoleBuilder.create().name("tmp-role").build();
+        realmResource.roles().create(role);
+        UserResource user = findUserByUsernameId(realmResource, "test-user@localhost");
+        UserManager.realm(realmResource).user(user).assignRoles(role.getName());
+
+        oauth.doLogin("test-user@localhost", "password");
+
+        EventRepresentation loginEvent = events.expectLogin().assertEvent();
+
+        loginEvent.getDetails().get(Details.CODE_ID);
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+
+        realmResource.roles().deleteRole("tmp-role");
+
+        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+
+        Assert.assertEquals(200, response.getStatusCode());
+
+        AccessToken token = oauth.verifyToken(response.getAccessToken());
+        Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
+        assertTrue(token.getRealmAccess().isUserInRole("user"));
+
+        events.clear();
+    }
+
+    @Test
+    public void accessTokenCodeHasRequiredAction() {
+
+        UserResource user = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost");
+        UserManager.realm(adminClient.realm("test")).user(user).addRequiredAction(UserModel.RequiredAction.UPDATE_PROFILE.toString());
+
+        oauth.doLogin("test-user@localhost", "password");
+
+        String code = driver.getPageSource().split("code=")[1].split("&")[0].split("\"")[0];
+
+        OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
+        Assert.assertEquals(400, response.getStatusCode());
+
+        EventRepresentation event = events.poll();
+        assertNotNull(event.getDetails().get(Details.CODE_ID));
+
+        UserManager.realm(adminClient.realm("test")).user(user).removeRequiredAction(UserModel.RequiredAction.UPDATE_PROFILE.toString());
+    }
+
+    @Test
+    public void testGrantAccessToken() throws Exception {
+        Client client = javax.ws.rs.client.ClientBuilder.newClient();
+        UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
+        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+        WebTarget grantTarget = client.target(grantUri);
+
+        {   // test checkSsl
+            {
+                RealmResource realmsResource = adminClient.realm("test");
+                RealmRepresentation realmRepresentation = realmsResource.toRepresentation();
+                realmRepresentation.setSslRequired(SslRequired.ALL.toString());
+                realmsResource.update(realmRepresentation);
+            }
+
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(403, response.getStatus());
+            response.close();
+
+            {
+                RealmResource realmsResource = realmsResouce().realm("test");
+                RealmRepresentation realmRepresentation = realmsResource.toRepresentation();
+                realmRepresentation.setSslRequired(SslRequired.EXTERNAL.toString());
+                realmsResource.update(realmRepresentation);
+            }
+
+        }
+
+        {   // test null username
+            String header = BasicAuthHelper.createHeader("test-app", "password");
+            Form form = new Form();
+            form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD);
+            form.param("password", "password");
+            Response response = grantTarget.request()
+                    .header(HttpHeaders.AUTHORIZATION, header)
+                    .post(Entity.form(form));
+            assertEquals(401, response.getStatus());
+            response.close();
+        }
+
+        {   // test no password
+            String header = BasicAuthHelper.createHeader("test-app", "password");
+            Form form = new Form();
+            form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD);
+            form.param("username", "test-user@localhost");
+            Response response = grantTarget.request()
+                    .header(HttpHeaders.AUTHORIZATION, header)
+                    .post(Entity.form(form));
+            assertEquals(401, response.getStatus());
+            response.close();
+        }
+
+        {   // test invalid password
+            String header = BasicAuthHelper.createHeader("test-app", "password");
+            Form form = new Form();
+            form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD);
+            form.param("username", "test-user@localhost");
+            form.param("password", "invalid");
+            Response response = grantTarget.request()
+                    .header(HttpHeaders.AUTHORIZATION, header)
+                    .post(Entity.form(form));
+            assertEquals(401, response.getStatus());
+            response.close();
+        }
+        {   // test no password
+            String header = BasicAuthHelper.createHeader("test-app", "password");
+            Form form = new Form();
+            form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD);
+            form.param("username", "test-user@localhost");
+            Response response = grantTarget.request()
+                    .header(HttpHeaders.AUTHORIZATION, header)
+                    .post(Entity.form(form));
+            assertEquals(401, response.getStatus());
+            response.close();
+        }
+
+        {   //test bearer-only
+
+            {
+                ClientResource clientResource = findClientByClientId(adminClient.realm("test"), "test-app");
+                ClientRepresentation clientRepresentation = clientResource.toRepresentation();
+                clientRepresentation.setBearerOnly(true);
+                clientResource.update(clientRepresentation);
+            }
+
+
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(400, response.getStatus());
+            response.close();
+
+            {
+                ClientResource clientResource = findClientByClientId(adminClient.realm("test"), "test-app");
+                ClientRepresentation clientRepresentation = clientResource.toRepresentation();
+                clientRepresentation.setBearerOnly(false);
+                clientResource.update(clientRepresentation);
+            }
+
+        }
+
+        {   // test realm disabled
+            {
+                RealmResource realmsResource = realmsResouce().realm("test");
+                RealmRepresentation realmRepresentation = realmsResource.toRepresentation();
+                realmRepresentation.setEnabled(false);
+                realmsResource.update(realmRepresentation);
+            }
+
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(403, response.getStatus());
+            response.close();
+
+            {
+                RealmResource realmsResource = realmsResouce().realm("test");
+                RealmRepresentation realmRepresentation = realmsResource.toRepresentation();
+                realmRepresentation.setEnabled(true);
+                realmsResource.update(realmRepresentation);
+            }
+
+        }
+
+        {   // test application disabled
+
+            {
+                ClientResource clientResource = findClientByClientId(adminClient.realm("test"), "test-app");
+                ClientRepresentation clientRepresentation = clientResource.toRepresentation();
+                clientRepresentation.setEnabled(false);
+                clientResource.update(clientRepresentation);
+            }
+
+
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(400, response.getStatus());
+            response.close();
+
+            {
+                ClientResource clientResource = findClientByClientId(adminClient.realm("test"), "test-app");
+                ClientRepresentation clientRepresentation = clientResource.toRepresentation();
+                clientRepresentation.setEnabled(true);
+                clientResource.update(clientRepresentation);
+
+            }
+
+        }
+
+        {   // test user action required
+
+            {
+                UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost");
+                UserRepresentation userRepresentation = userResource.toRepresentation();
+                userRepresentation.getRequiredActions().add(UserModel.RequiredAction.UPDATE_PASSWORD.toString());
+                userResource.update(userRepresentation);
+            }
+
+
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(400, response.getStatus());
+            response.close();
+
+            {
+                UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost");
+                UserRepresentation userRepresentation = userResource.toRepresentation();
+                userRepresentation.getRequiredActions().remove(UserModel.RequiredAction.UPDATE_PASSWORD.toString());
+                userResource.update(userRepresentation);
+            }
+
+        }
+
+        {   // test user disabled
+            {
+                UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost");
+                UserRepresentation userRepresentation = userResource.toRepresentation();
+                userRepresentation.setEnabled(false);
+                userResource.update(userRepresentation);
+            }
+
+
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(400, response.getStatus());
+            response.close();
+
+            {
+                UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost");
+                UserRepresentation userRepresentation = userResource.toRepresentation();
+                userRepresentation.setEnabled(true);
+                userResource.update(userRepresentation);
+            }
+
+        }
+
+        {
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(200, response.getStatus());
+            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+            response.close();
+        }
+
+        client.close();
+        events.clear();
+    }
+
+    @Test
+    public void testKeycloak2221() throws Exception {
+        Client client = javax.ws.rs.client.ClientBuilder.newClient();
+        UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
+        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+        WebTarget grantTarget = client.target(grantUri);
+
+        ClientResource clientResource;
+
+        {
+
+            clientResource = findClientByClientId(adminClient.realm("test"), "test-app");
+            clientResource.getProtocolMappers().createMapper(createRoleNameMapper("rename-role", "user", "realm-user"));
+            clientResource.getProtocolMappers().createMapper(createRoleNameMapper("rename-role2", "admin", "the-admin"));
+
+        }
+
+        {
+            Response response = executeGrantRequest(grantTarget, "no-permissions", "password");
+            assertEquals(200, response.getStatus());
+            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+            AccessToken accessToken = getAccessToken(tokenResponse);
+            assertEquals(accessToken.getRealmAccess().getRoles().size(), 1);
+            assertTrue(accessToken.getRealmAccess().getRoles().contains("realm-user"));
+
+            response.close();
+        }
+
+        // undo mappers
+        {
+            ClientResource app = findClientByClientId(adminClient.realm("test"), "test-app");
+            ClientRepresentation clientRepresentation = app.toRepresentation();
+            for (ProtocolMapperRepresentation protocolRep : clientRepresentation.getProtocolMappers()) {
+                if (protocolRep.getName().startsWith("rename-role")) {
+                    clientResource.getProtocolMappers().delete(protocolRep.getId());
+                }
+            }
+        }
+
+        events.clear();
+
+    }
+
+    @Test
+    public void testTokenMapping() throws Exception {
+        Client client = javax.ws.rs.client.ClientBuilder.newClient();
+        UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
+        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+        WebTarget grantTarget = client.target(grantUri);
+        {
+            UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost");
+            UserRepresentation user = userResource.toRepresentation();
+
+            user.singleAttribute("street", "5 Yawkey Way");
+            user.singleAttribute("locality", "Boston");
+            user.singleAttribute("region", "MA");
+            user.singleAttribute("postal_code", "02115");
+            user.singleAttribute("country", "USA");
+            user.singleAttribute("phone", "617-777-6666");
+
+            List<String> departments = Arrays.asList("finance", "development");
+            user.getAttributes().put("departments", departments);
+            userResource.update(user);
+
+            ClientResource app = findClientResourceByClientId(adminClient.realm("test"), "test-app");
+
+            ProtocolMapperRepresentation mapper = createAddressMapper(true, true);
+            app.getProtocolMappers().createMapper(mapper);
+
+            ProtocolMapperRepresentation hard = createHardcodedClaim("hard", "hard", "coded", "String", false, null, true, true);
+            app.getProtocolMappers().createMapper(hard);
+            app.getProtocolMappers().createMapper(createHardcodedClaim("hard-nested", "nested.hard", "coded-nested", "String", false, null, true, true));
+            app.getProtocolMappers().createMapper(createClaimMapper("custom phone", "phone", "home_phone", "String", true, "", true, true, false));
+            app.getProtocolMappers().createMapper(createClaimMapper("nested phone", "phone", "home.phone", "String", true, "", true, true, false));
+            app.getProtocolMappers().createMapper(createClaimMapper("departments", "departments", "department", "String", true, "", true, true, true));
+            app.getProtocolMappers().createMapper(createHardcodedRole("hard-realm", "hardcoded"));
+            app.getProtocolMappers().createMapper(createHardcodedRole("hard-app", "app.hardcoded"));
+            app.getProtocolMappers().createMapper(createRoleNameMapper("rename-app-role", "test-app.customer-user", "realm-user"));
+        }
+
+        {
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(200, response.getStatus());
+
+            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+            IDToken idToken = getIdToken(tokenResponse);
+            assertNotNull(idToken.getAddress());
+            assertEquals(idToken.getName(), "Tom Brady");
+            assertEquals(idToken.getAddress().getStreetAddress(), "5 Yawkey Way");
+            assertEquals(idToken.getAddress().getLocality(), "Boston");
+            assertEquals(idToken.getAddress().getRegion(), "MA");
+            assertEquals(idToken.getAddress().getPostalCode(), "02115");
+            assertEquals(idToken.getAddress().getCountry(), "USA");
+            assertNotNull(idToken.getOtherClaims().get("home_phone"));
+            assertEquals("617-777-6666", idToken.getOtherClaims().get("home_phone"));
+            assertEquals("coded", idToken.getOtherClaims().get("hard"));
+            Map nested = (Map) idToken.getOtherClaims().get("nested");
+            assertEquals("coded-nested", nested.get("hard"));
+            nested = (Map) idToken.getOtherClaims().get("home");
+            assertEquals("617-777-6666", nested.get("phone"));
+            List<String> departments = (List<String>) idToken.getOtherClaims().get("department");
+            assertEquals(2, departments.size());
+            assertTrue(departments.contains("finance") && departments.contains("development"));
+
+            AccessToken accessToken = getAccessToken(tokenResponse);
+            assertEquals(accessToken.getName(), "Tom Brady");
+            assertNotNull(accessToken.getAddress());
+            assertEquals(accessToken.getAddress().getStreetAddress(), "5 Yawkey Way");
+            assertEquals(accessToken.getAddress().getLocality(), "Boston");
+            assertEquals(accessToken.getAddress().getRegion(), "MA");
+            assertEquals(accessToken.getAddress().getPostalCode(), "02115");
+            assertEquals(accessToken.getAddress().getCountry(), "USA");
+            assertNotNull(accessToken.getOtherClaims().get("home_phone"));
+            assertEquals("617-777-6666", accessToken.getOtherClaims().get("home_phone"));
+            assertEquals("coded", accessToken.getOtherClaims().get("hard"));
+            nested = (Map) accessToken.getOtherClaims().get("nested");
+            assertEquals("coded-nested", nested.get("hard"));
+            nested = (Map) accessToken.getOtherClaims().get("home");
+            assertEquals("617-777-6666", nested.get("phone"));
+            departments = (List<String>) idToken.getOtherClaims().get("department");
+            assertEquals(2, departments.size());
+            assertTrue(departments.contains("finance") && departments.contains("development"));
+            assertTrue(accessToken.getRealmAccess().getRoles().contains("hardcoded"));
+            assertTrue(accessToken.getRealmAccess().getRoles().contains("realm-user"));
+            Assert.assertFalse(accessToken.getResourceAccess("test-app").getRoles().contains("customer-user"));
+            assertTrue(accessToken.getResourceAccess("app").getRoles().contains("hardcoded"));
+
+
+            response.close();
+        }
+
+        // undo mappers
+        {
+            ClientResource app = findClientByClientId(adminClient.realm("test"), "test-app");
+            ClientRepresentation clientRepresentation = app.toRepresentation();
+            for (ProtocolMapperRepresentation model : clientRepresentation.getProtocolMappers()) {
+                if (model.getName().equals("address")
+                        || model.getName().equals("hard")
+                        || model.getName().equals("hard-nested")
+                        || model.getName().equals("custom phone")
+                        || model.getName().equals("departments")
+                        || model.getName().equals("nested phone")
+                        || model.getName().equals("rename-app-role")
+                        || model.getName().equals("hard-realm")
+                        || model.getName().equals("hard-app")
+                        ) {
+                    app.getProtocolMappers().delete(model.getId());
+                }
+            }
+        }
+
+        events.clear();
+
+
+        {
+            Response response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(200, response.getStatus());
+            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+            IDToken idToken = getIdToken(tokenResponse);
+            assertNull(idToken.getAddress());
+            assertNull(idToken.getOtherClaims().get("home_phone"));
+            assertNull(idToken.getOtherClaims().get("hard"));
+            assertNull(idToken.getOtherClaims().get("nested"));
+            assertNull(idToken.getOtherClaims().get("department"));
+
+            response.close();
+        }
+
+
+        events.clear();
+        client.close();
+
+
+    }
+
+    @Test
+    public void testClientTemplate() throws Exception {
+        RealmResource realm = adminClient.realm("test");
+        RoleRepresentation realmRole = new RoleRepresentation();
+        realmRole.setName("realm-test-role");
+        realm.roles().create(realmRole);
+        realmRole = realm.roles().get("realm-test-role").toRepresentation();
+        RoleRepresentation realmRole2 = new RoleRepresentation();
+        realmRole2.setName("realm-test-role2");
+        realm.roles().create(realmRole2);
+        realmRole2 = realm.roles().get("realm-test-role2").toRepresentation();
+
+
+        List<UserRepresentation> users = realm.users().search("test-user@localhost", -1, -1);
+        assertEquals(1, users.size());
+        UserRepresentation user = users.get(0);
+
+        List<RoleRepresentation> addRoles = new LinkedList<>();
+        addRoles.add(realmRole);
+        addRoles.add(realmRole2);
+        realm.users().get(user.getId()).roles().realmLevel().add(addRoles);
+
+        ClientTemplateRepresentation rep = new ClientTemplateRepresentation();
+        rep.setName("template");
+        rep.setProtocol("oidc");
+        Response response = realm.clientTemplates().create(rep);
+        assertEquals(201, response.getStatus());
+        URI templateUri = response.getLocation();
+        response.close();
+        ClientTemplateResource templateResource = adminClient.proxy(ClientTemplateResource.class, templateUri);
+        ProtocolMapperModel hard = HardcodedClaim.create("hard", "hard", "coded", "String", false, null, true, true);
+        ProtocolMapperRepresentation mapper = ModelToRepresentation.toRepresentation(hard);
+        response = templateResource.getProtocolMappers().createMapper(mapper);
+        assertEquals(201, response.getStatus());
+        response.close();
+        List<ClientRepresentation> clients = realm.clients().findAll();
+        ClientRepresentation clientRep = null;
+        for (ClientRepresentation c : clients) {
+            if (c.getClientId().equals("test-app")) {
+                clientRep = c;
+                break;
+            }
+
+        }
+        clientRep.setClientTemplate("template");
+        clientRep.setFullScopeAllowed(false);
+        clientRep.setUseTemplateMappers(true);
+        clientRep.setUseTemplateScope(true);
+        clientRep.setUseTemplateConfig(true);
+        realm.clients().get(clientRep.getId()).update(clientRep);
+
+        {
+            Client client = javax.ws.rs.client.ClientBuilder.newClient();
+            UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
+            URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+            WebTarget grantTarget = client.target(grantUri);
+
+            response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(200, response.getStatus());
+            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+            IDToken idToken = getIdToken(tokenResponse);
+            assertEquals("coded", idToken.getOtherClaims().get("hard"));
+
+            AccessToken accessToken = getAccessToken(tokenResponse);
+            assertEquals("coded", accessToken.getOtherClaims().get("hard"));
+
+            // check zero scope for template
+            Assert.assertFalse(accessToken.getRealmAccess().getRoles().contains(realmRole.getName()));
+            Assert.assertFalse(accessToken.getRealmAccess().getRoles().contains(realmRole2.getName()));
+
+
+            response.close();
+            client.close();
+        }
+
+        // test that scope is added
+        List<RoleRepresentation> addRole1 = new LinkedList<>();
+        addRole1.add(realmRole);
+        templateResource.getScopeMappings().realmLevel().add(addRole1);
+
+        {
+            Client client = javax.ws.rs.client.ClientBuilder.newClient();
+            UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
+            URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+            WebTarget grantTarget = client.target(grantUri);
+
+            response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(200, response.getStatus());
+            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+            AccessToken accessToken = getAccessToken(tokenResponse);
+            // check zero scope for template
+            assertNotNull(accessToken.getRealmAccess());
+            assertTrue(accessToken.getRealmAccess().getRoles().contains(realmRole.getName()));
+            Assert.assertFalse(accessToken.getRealmAccess().getRoles().contains(realmRole2.getName()));
+
+
+            response.close();
+            client.close();
+        }
+
+        // test combined scopes
+        List<RoleRepresentation> addRole2 = new LinkedList<>();
+        addRole2.add(realmRole2);
+        realm.clients().get(clientRep.getId()).getScopeMappings().realmLevel().add(addRole2);
+
+        {
+            Client client = javax.ws.rs.client.ClientBuilder.newClient();
+            UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
+            URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+            WebTarget grantTarget = client.target(grantUri);
+
+            response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(200, response.getStatus());
+            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+
+            AccessToken accessToken = getAccessToken(tokenResponse);
+
+            // check zero scope for template
+            assertNotNull(accessToken.getRealmAccess());
+            assertTrue(accessToken.getRealmAccess().getRoles().contains(realmRole.getName()));
+            assertTrue(accessToken.getRealmAccess().getRoles().contains(realmRole2.getName()));
+
+
+            response.close();
+            client.close();
+        }
+
+        // remove scopes and retest
+        templateResource.getScopeMappings().realmLevel().remove(addRole1);
+        realm.clients().get(clientRep.getId()).getScopeMappings().realmLevel().remove(addRole2);
+
+        {
+            Client client = javax.ws.rs.client.ClientBuilder.newClient();
+            UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
+            URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+            WebTarget grantTarget = client.target(grantUri);
+
+            response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(200, response.getStatus());
+            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+
+            AccessToken accessToken = getAccessToken(tokenResponse);
+            Assert.assertFalse(accessToken.getRealmAccess().getRoles().contains(realmRole.getName()));
+            Assert.assertFalse(accessToken.getRealmAccess().getRoles().contains(realmRole2.getName()));
+
+
+            response.close();
+            client.close();
+        }
+
+        // test full scope on template
+        rep.setFullScopeAllowed(true);
+        templateResource.update(rep);
+
+        {
+            Client client = javax.ws.rs.client.ClientBuilder.newClient();
+            UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
+            URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+            WebTarget grantTarget = client.target(grantUri);
+
+            response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(200, response.getStatus());
+            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+
+            AccessToken accessToken = getAccessToken(tokenResponse);
+
+            // check zero scope for template
+            assertNotNull(accessToken.getRealmAccess());
+            assertTrue(accessToken.getRealmAccess().getRoles().contains(realmRole.getName()));
+            assertTrue(accessToken.getRealmAccess().getRoles().contains(realmRole2.getName()));
+
+
+            response.close();
+            client.close();
+        }
+
+        // test don't use template scope
+        clientRep.setUseTemplateScope(false);
+        realm.clients().get(clientRep.getId()).update(clientRep);
+
+        {
+            Client client = javax.ws.rs.client.ClientBuilder.newClient();
+            UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
+            URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+            WebTarget grantTarget = client.target(grantUri);
+
+            response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(200, response.getStatus());
+            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+
+            AccessToken accessToken = getAccessToken(tokenResponse);
+            Assert.assertFalse(accessToken.getRealmAccess().getRoles().contains(realmRole.getName()));
+            Assert.assertFalse(accessToken.getRealmAccess().getRoles().contains(realmRole2.getName()));
+
+
+            response.close();
+            client.close();
+        }
+
+        // undo mappers
+        clientRep.setClientTemplate(ClientTemplateRepresentation.NONE);
+        clientRep.setFullScopeAllowed(true);
+        realm.clients().get(clientRep.getId()).update(clientRep);
+        realm.users().get(user.getId()).roles().realmLevel().remove(addRoles);
+        realm.roles().get(realmRole.getName()).remove();
+        realm.roles().get(realmRole2.getName()).remove();
+        templateResource.remove();
+
+        {
+            Client client = javax.ws.rs.client.ClientBuilder.newClient();
+            UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
+            URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+            WebTarget grantTarget = client.target(grantUri);
+
+            response = executeGrantAccessTokenRequest(grantTarget);
+            assertEquals(200, response.getStatus());
+            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
+            IDToken idToken = getIdToken(tokenResponse);
+            assertNull(idToken.getOtherClaims().get("hard"));
+
+            AccessToken accessToken = getAccessToken(tokenResponse);
+            assertNull(accessToken.getOtherClaims().get("hard"));
+
+
+            response.close();
+            client.close();
+        }
+        events.clear();
+
+    }
+
+    // KEYCLOAK-1595 Assert that public client is able to retrieve token even if header "Authorization: Negotiate something" was used (parameter client_id has preference in this case)
+    @Test
+    public void testAuthorizationNegotiateHeaderIgnored() throws Exception {
+
+        adminClient.realm("test").clients().create(ClientBuilder.create()
+                .clientId("sample-public-client")
+                .authenticatorType("client-secret")
+                .redirectUris("http://localhost:8180/auth/realms/master/app/*")
+                .publicClient()
+                .build());
+
+        oauth.clientId("sample-public-client");
+        oauth.doLogin("test-user@localhost", "password");
+        EventRepresentation loginEvent = events.expectLogin().client("sample-public-client").assertEvent();
+
+        String sessionId = loginEvent.getSessionId();
+        String codeId = loginEvent.getDetails().get(Details.CODE_ID);
+
+        String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+
+        CloseableHttpClient client = new DefaultHttpClient();
+        try {
+            HttpPost post = new HttpPost(oauth.getAccessTokenUrl());
+
+            List<NameValuePair> parameters = new LinkedList<NameValuePair>();
+            parameters.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, OAuth2Constants.AUTHORIZATION_CODE));
+            parameters.add(new BasicNameValuePair(OAuth2Constants.CODE, code));
+            parameters.add(new BasicNameValuePair(OAuth2Constants.REDIRECT_URI, oauth.getRedirectUri()));
+            parameters.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, oauth.getClientId()));
+            post.setHeader("Authorization", "Negotiate something-which-will-be-ignored");
+
+            UrlEncodedFormEntity formEntity = null;
+            formEntity = new UrlEncodedFormEntity(parameters, "UTF-8");
+            post.setEntity(formEntity);
+
+            OAuthClient.AccessTokenResponse response = new OAuthClient.AccessTokenResponse(client.execute(post));
+            Assert.assertEquals(200, response.getStatusCode());
+            AccessToken token = oauth.verifyToken(response.getAccessToken());
+            events.expectCodeToToken(codeId, sessionId).client("sample-public-client").assertEvent();
+        } finally {
+            oauth.closeClient(client);
+        }
+    }
+
+    private IDToken getIdToken(org.keycloak.representations.AccessTokenResponse tokenResponse) throws JWSInputException {
+        JWSInput input = new JWSInput(tokenResponse.getIdToken());
+        return input.readJsonContent(IDToken.class);
+    }
+
+    private AccessToken getAccessToken(org.keycloak.representations.AccessTokenResponse tokenResponse) throws JWSInputException {
+        JWSInput input = new JWSInput(tokenResponse.getToken());
+        return input.readJsonContent(AccessToken.class);
+    }
+
+    protected Response executeGrantAccessTokenRequest(WebTarget grantTarget) {
+        String username = "test-user@localhost";
+        String password = "password";
+        return executeGrantRequest(grantTarget, username, password);
+    }
+
+    protected Response executeGrantRequest(WebTarget grantTarget, String username, String password) {
+        String header = BasicAuthHelper.createHeader("test-app", "password");
+        Form form = new Form();
+        form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD)
+                .param("username", username)
+                .param("password", password);
+        return grantTarget.request()
+                .header(HttpHeaders.AUTHORIZATION, header)
+                .post(Entity.form(form));
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java
index b3f3c8d..24395ab 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java
@@ -17,17 +17,10 @@
 
 package org.keycloak.testsuite.util;
 
-import org.codehaus.plexus.util.xml.pull.XmlSerializer;
 import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.representations.idm.UserRepresentation;
 
-import javax.ws.rs.client.Client;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
 import java.util.Map;
 
 /**
@@ -83,7 +76,6 @@ public class ClientBuilder {
         Map<String, String> attributes = new HashMap<String, String>();
         attributes.put(name, value);
         rep.setAttributes(attributes);
-
         return this;
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ProtocolMapperUtil.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ProtocolMapperUtil.java
new file mode 100644
index 0000000..d9f560a
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ProtocolMapperUtil.java
@@ -0,0 +1,93 @@
+package org.keycloak.testsuite.util;
+
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.protocol.oidc.mappers.AddressMapper;
+import org.keycloak.protocol.oidc.mappers.HardcodedClaim;
+import org.keycloak.protocol.oidc.mappers.HardcodedRole;
+import org.keycloak.protocol.oidc.mappers.RoleNameMapper;
+import org.keycloak.protocol.oidc.mappers.UserAttributeMapper;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
+
+/**
+ * @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>.
+ */
+public class ProtocolMapperUtil {
+
+    /**
+     * This is the migration of the method present at RoleNameMapper
+     *
+     * @param name
+     * @param role
+     * @param newName
+     * @return
+     */
+    public static ProtocolMapperRepresentation createRoleNameMapper(String name,
+                                                                    String role,
+                                                                    String newName) {
+        return ModelToRepresentation.toRepresentation(RoleNameMapper.create(name, role, newName));
+
+    }
+
+    public static ProtocolMapperRepresentation createHardcodedRole(String name,
+                                                                   String role) {
+        return ModelToRepresentation.toRepresentation(HardcodedRole.create(name, role));
+    }
+
+    /**
+     * This is the migration of the method present at AddressMapper
+     *
+     * @param idToken
+     * @param accessToken
+     * @return
+     */
+    public static ProtocolMapperRepresentation createAddressMapper(boolean idToken, boolean accessToken) {
+        return ModelToRepresentation.toRepresentation(AddressMapper.createAddressMapper(idToken, accessToken));
+    }
+
+    /**
+     * This is the migration of the method present at HardcodedClaim
+     *
+     * @param name
+     * @param hardcodedName
+     * @param hardcodedValue
+     * @param claimType
+     * @param consentRequired
+     * @param consentText
+     * @param accessToken
+     * @param idToken
+     * @return
+     */
+    public static ProtocolMapperRepresentation createHardcodedClaim(String name,
+                                                                    String hardcodedName,
+                                                                    String hardcodedValue, String claimType,
+                                                                    boolean consentRequired, String consentText,
+                                                                    boolean accessToken, boolean idToken) {
+        return ModelToRepresentation.toRepresentation(HardcodedClaim.create(name, hardcodedName, hardcodedValue,
+                claimType, consentRequired, consentText, accessToken, idToken));
+    }
+
+    /**
+     * Migrated from UserAttributeMapper
+     *
+     * @param name
+     * @param userAttribute
+     * @param tokenClaimName
+     * @param claimType
+     * @param consentRequired
+     * @param consentText
+     * @param accessToken
+     * @param idToken
+     * @param multivalued
+     * @return
+     */
+    public static ProtocolMapperRepresentation createClaimMapper(String name,
+                                                                 String userAttribute,
+                                                                 String tokenClaimName, String claimType,
+                                                                 boolean consentRequired, String consentText,
+                                                                 boolean accessToken, boolean idToken, boolean multivalued) {
+        return ModelToRepresentation.toRepresentation(UserAttributeMapper.createClaimMapper(name, userAttribute, tokenClaimName,
+                claimType, consentRequired, consentText, accessToken, idToken, multivalued));
+
+    }
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/RealmManager.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/RealmManager.java
new file mode 100644
index 0000000..59b9486
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/RealmManager.java
@@ -0,0 +1,26 @@
+package org.keycloak.testsuite.util;
+
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.representations.idm.RealmRepresentation;
+
+/**
+ * @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>.
+ */
+public class RealmManager {
+
+    private static RealmResource realm;
+
+    private RealmManager() {
+    }
+
+    public static RealmManager realm(RealmResource realm) {
+        RealmManager.realm = realm;
+        return new RealmManager();
+    }
+
+    public void accessCodeLifeSpan(Integer accessCodeLifespan) {
+        RealmRepresentation realmRepresentation = realm.toRepresentation();
+        realmRepresentation.setAccessCodeLifespan(accessCodeLifespan);
+        realm.update(realmRepresentation);
+    }
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java
index ae427e1..a8a0cbe 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java
@@ -20,6 +20,7 @@ package org.keycloak.testsuite.util;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -91,8 +92,9 @@ public class UserBuilder {
 
     public UserBuilder role(String role) {
         if (rep.getRealmRoles() == null) {
-            rep.setRealmRoles(new LinkedList<String>());
+            rep.setRealmRoles(new ArrayList<String>());
         }
+        rep.getRealmRoles().add(role);
         return this;
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserManager.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserManager.java
new file mode 100644
index 0000000..ed797b5
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserManager.java
@@ -0,0 +1,74 @@
+package org.keycloak.testsuite.util;
+
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.admin.client.resource.UserResource;
+import org.keycloak.representations.idm.UserRepresentation;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import static org.keycloak.testsuite.admin.ApiUtil.findUserByUsernameId;
+
+/**
+ * @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>.
+ */
+public class UserManager {
+
+    private static RealmResource realm;
+
+    private UserManager() {
+    }
+
+    public static UserManager realm(RealmResource realm) {
+        UserManager.realm = realm;
+        return new UserManager();
+    }
+
+    public UserManagerBuilder username(String username) {
+        return new UserManagerBuilder(findUserByUsernameId(realm, username));
+    }
+
+    public UserManagerBuilder user(UserResource user) {
+        return new UserManagerBuilder(user);
+    }
+
+    public class UserManagerBuilder {
+
+        private final UserResource userResource;
+
+        public UserManagerBuilder(UserResource userResource) {
+            this.userResource = userResource;
+        }
+
+        public void removeRequiredAction(String action) {
+            UserRepresentation user = initializeRequiredActions();
+            user.getRequiredActions().remove(action);
+            userResource.update(user);
+        }
+
+        public void addRequiredAction(String... actions) {
+            UserRepresentation user = initializeRequiredActions();
+            user.setRequiredActions(Arrays.asList(actions));
+            userResource.update(user);
+        }
+
+        public void assignRoles(String... roles) {
+            UserRepresentation user = userResource.toRepresentation();
+            if (user != null && user.getRealmRoles() == null) {
+                user.setRealmRoles(new ArrayList<String>());
+            }
+            user.setRealmRoles(Arrays.asList(roles));
+            userResource.update(user);
+        }
+
+
+        private UserRepresentation initializeRequiredActions() {
+            UserRepresentation user = userResource.toRepresentation();
+            if (user != null && user.getRequiredActions() == null) {
+                user.setRequiredActions(new ArrayList<String>());
+            }
+            return user;
+        }
+
+    }
+}
\ No newline at end of file