keycloak-developers

Merge pull request #546 from stianst/access-code Remove

7/22/2014 5:37:54 AM

Details

diff --git a/core/src/main/java/org/keycloak/representations/AccessCode.java b/core/src/main/java/org/keycloak/representations/AccessCode.java
index 1ecebb2..9fe860e 100755
--- a/core/src/main/java/org/keycloak/representations/AccessCode.java
+++ b/core/src/main/java/org/keycloak/representations/AccessCode.java
@@ -1,6 +1,5 @@
 package org.keycloak.representations;
 
-import java.util.HashSet;
 import java.util.Set;
 
 /**
@@ -10,15 +9,18 @@ import java.util.Set;
  */
 public class AccessCode {
     protected String id;
+    protected String clientId;
+    protected String userId;
     protected String usernameUsed;
     protected String state;
+    protected String sessionState;
     protected String redirectUri;
     protected boolean rememberMe;
     protected String authMethod;
     protected int timestamp;
     protected int expiration;
-    protected AccessToken accessToken;
     protected Set<String> requiredActions;
+    protected Set<String> requestedRoles;
 
     public String getId() {
         return id;
@@ -28,6 +30,22 @@ public class AccessCode {
         this.id = id;
     }
 
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
     public String getState() {
         return state;
     }
@@ -36,6 +54,14 @@ public class AccessCode {
         this.state = state;
     }
 
+    public String getSessionState() {
+        return sessionState;
+    }
+
+    public void setSessionState(String sessionState) {
+        this.sessionState = sessionState;
+    }
+
     public String getRedirectUri() {
         return redirectUri;
     }
@@ -68,14 +94,6 @@ public class AccessCode {
         this.expiration = expiration;
     }
 
-    public AccessToken getAccessToken() {
-        return accessToken;
-    }
-
-    public void setAccessToken(AccessToken accessToken) {
-        this.accessToken = accessToken;
-    }
-
     public int getTimestamp() {
         return timestamp;
     }
@@ -99,4 +117,12 @@ public class AccessCode {
     public void setUsernameUsed(String usernameUsed) {
         this.usernameUsed = usernameUsed;
     }
+
+    public Set<String> getRequestedRoles() {
+        return requestedRoles;
+    }
+
+    public void setRequestedRoles(Set<String> requestedRoles) {
+        this.requestedRoles = requestedRoles;
+    }
 }
diff --git a/services/src/main/java/org/keycloak/services/managers/AccessCodeEntry.java b/services/src/main/java/org/keycloak/services/managers/AccessCodeEntry.java
index 179e730..f5afe34 100755
--- a/services/src/main/java/org/keycloak/services/managers/AccessCodeEntry.java
+++ b/services/src/main/java/org/keycloak/services/managers/AccessCodeEntry.java
@@ -1,9 +1,11 @@
 package org.keycloak.services.managers;
 
+import org.keycloak.OAuthErrorException;
 import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserModel.RequiredAction;
 import org.keycloak.representations.AccessCode;
@@ -33,29 +35,45 @@ public class AccessCodeEntry {
     }
 
     public UserModel getUser() {
-        return keycloakSession.users().getUserById(accessCode.getAccessToken().getSubject(), realm);
+        return keycloakSession.users().getUserById(accessCode.getUserId(), realm);
     }
 
     public String getSessionState() {
-        return accessCode.getAccessToken().getSessionState();
+        return accessCode.getSessionState();
+    }
+
+    public void setSessionState(String state) {
+        accessCode.setSessionState(state);
     }
 
     public boolean isExpired() {
         return accessCode.getExpiration() != 0 && Time.currentTime() > accessCode.getExpiration();
     }
 
-    public AccessToken getToken() {
-        return accessCode.getAccessToken();
+    public Set<RoleModel> getRequestedRoles() {
+        Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
+        for (String roleId : accessCode.getRequestedRoles()) {
+            RoleModel role = realm.getRoleById(roleId);
+            if (role == null) {
+                new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid role " + roleId);
+            }
+            requestedRoles.add(realm.getRoleById(roleId));
+        }
+        return requestedRoles;
     }
 
     public ClientModel getClient() {
-        return realm.findClient(accessCode.getAccessToken().getIssuedFor());
+        return realm.findClient(accessCode.getClientId());
     }
 
     public String getState() {
         return accessCode.getState();
     }
 
+    public void setState(String state) {
+        accessCode.setState(state);
+    }
+
     public String getRedirectUri() {
         return accessCode.getRedirectUri();
     }
diff --git a/services/src/main/java/org/keycloak/services/managers/TokenManager.java b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
index e8e1161..e5ba119 100755
--- a/services/src/main/java/org/keycloak/services/managers/TokenManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
@@ -1,7 +1,6 @@
 package org.keycloak.services.managers;
 
 import org.jboss.logging.Logger;
-import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
 import org.keycloak.OAuthErrorException;
 import org.keycloak.audit.Audit;
 import org.keycloak.audit.Details;
@@ -24,12 +23,9 @@ import org.keycloak.representations.IDToken;
 import org.keycloak.representations.RefreshToken;
 import org.keycloak.util.Time;
 
-import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.UriInfo;
 import java.io.IOException;
 import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
@@ -80,21 +76,24 @@ public class TokenManager {
     }
 
     private AccessCodeEntry createAccessCodeEntry(String scopeParam, String state, String redirect, KeycloakSession keycloakSession, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session) {
-        List<RoleModel> realmRolesRequested = new LinkedList<RoleModel>();
-        MultivaluedMap<String, RoleModel> resourceRolesRequested = new MultivaluedMapImpl<String, RoleModel>();
-
-        AccessToken token = createClientAccessToken(scopeParam, realm, client, user, session, realmRolesRequested, resourceRolesRequested);
-        if (session != null) token.setSessionState(session.getId());
         AccessCode code = new AccessCode();
         code.setId(UUID.randomUUID().toString() + System.currentTimeMillis());
-        code.setAccessToken(token);
+        code.setClientId(client.getClientId());
+        code.setUserId(user.getId());
         code.setTimestamp(Time.currentTime());
         code.setExpiration(Time.currentTime() + realm.getAccessCodeLifespan());
-        code.setState(state);
+        code.setSessionState(session != null ? session.getId() : null);
         code.setRedirectUri(redirect);
+        code.setState(state);
+
+        Set<String> requestedRoles = new HashSet<String>();
+        for (RoleModel r : getAccess(scopeParam, client, user)) {
+            requestedRoles.add(r.getId());
+        }
+        code.setRequestedRoles(requestedRoles);
+
         AccessCodeEntry entry = new AccessCodeEntry(keycloakSession, realm, code);
         return entry;
-
     }
 
     public AccessToken refreshAccessToken(KeycloakSession session, UriInfo uriInfo, RealmModel realm, ClientModel client, String encodedRefreshToken, Audit audit) throws OAuthErrorException {
@@ -142,44 +141,7 @@ public class TokenManager {
             throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
         }
 
-        ApplicationModel clientApp = (client instanceof ApplicationModel) ? (ApplicationModel)client : null;
-
-
-        if (refreshToken.getRealmAccess() != null) {
-            for (String roleName : refreshToken.getRealmAccess().getRoles()) {
-                RoleModel role = realm.getRole(roleName);
-                if (role == null) {
-                    throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid realm role " + roleName);
-                }
-                if (!user.hasRole(role)) {
-                    throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for realm role: " + roleName);
-                }
-                if (!client.hasScope(role)) {
-                    throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Client no longer has realm scope: " + roleName);
-                }
-            }
-        }
-        if (refreshToken.getResourceAccess() != null) {
-            for (Map.Entry<String, AccessToken.Access> entry : refreshToken.getResourceAccess().entrySet()) {
-                ApplicationModel app = realm.getApplicationByName(entry.getKey());
-                if (app == null) {
-                    throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Application no longer exists", "Application no longer exists: " + app.getName());
-                }
-                for (String roleName : entry.getValue().getRoles()) {
-                    RoleModel role = app.getRole(roleName);
-                    if (role == null) {
-                        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", "Unknown application role: " + roleName);
-                    }
-                    if (!user.hasRole(role)) {
-                        throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for application role " + roleName);
-                    }
-                    if (clientApp != null && !clientApp.equals(app) && !client.hasScope(role)) {
-                        throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Client no longer has application scope" + roleName);
-                    }
-                }
-
-            }
-        }
+        verifyAccess(refreshToken, realm, client, user);
 
         AccessToken accessToken = initToken(realm, client, user, userSession);
         accessToken.setRealmAccess(refreshToken.getRealmAccess());
@@ -193,54 +155,73 @@ public class TokenManager {
         return accessToken;
     }
 
-    public AccessToken createClientAccessToken(String scopeParam, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session) {
-        return createClientAccessToken(scopeParam, realm, client, user, session, new LinkedList<RoleModel>(), new MultivaluedMapImpl<String, RoleModel>());
+    public AccessToken createClientAccessToken(Set<RoleModel> requestedRoles, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session) {
+        AccessToken token = initToken(realm, client, user, session);
+        for (RoleModel role : requestedRoles) {
+            addComposites(token, role);
+        }
+        return token;
     }
 
-    public AccessToken createClientAccessToken(String scopeParam, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, List<RoleModel> realmRolesRequested, MultivaluedMap<String, RoleModel> resourceRolesRequested) {
+    public Set<RoleModel> getAccess(String scopeParam, ClientModel client, UserModel user) {
         // todo scopeParam is ignored until we figure out a scheme that fits with openid connect
+        Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
 
         Set<RoleModel> roleMappings = user.getRoleMappings();
         Set<RoleModel> scopeMappings = client.getScopeMappings();
-        ApplicationModel clientApp = (client instanceof ApplicationModel) ? (ApplicationModel)client : null;
-        Set<RoleModel> clientAppRoles = clientApp == null ? null : clientApp.getRoles();
-        if (clientAppRoles != null) scopeMappings.addAll(clientAppRoles);
-
-        Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
+        if (client instanceof ApplicationModel) {
+            scopeMappings.addAll(((ApplicationModel) client).getRoles());
+        }
 
         for (RoleModel role : roleMappings) {
-            if (clientApp != null && role.getContainer().equals(clientApp)) requestedRoles.add(role);
             for (RoleModel desiredRole : scopeMappings) {
                 Set<RoleModel> visited = new HashSet<RoleModel>();
                 applyScope(role, desiredRole, visited, requestedRoles);
             }
         }
 
-        for (RoleModel role : requestedRoles) {
-            if (role.getContainer() instanceof RealmModel) {
-                realmRolesRequested.add(role);
-            } else if (role.getContainer() instanceof ApplicationModel) {
-                ApplicationModel app = (ApplicationModel)role.getContainer();
-                resourceRolesRequested.add(app.getName(), role);
-            }
-        }
+        return requestedRoles;
+    }
+
+    public void verifyAccess(AccessToken token, RealmModel realm, ClientModel client, UserModel user) throws OAuthErrorException {
+        ApplicationModel clientApp = (client instanceof ApplicationModel) ? (ApplicationModel)client : null;
 
-        AccessToken token = initToken(realm, client, user, session);
 
-        if (realmRolesRequested.size() > 0) {
-            for (RoleModel role : realmRolesRequested) {
-                addComposites(token, role);
+        if (token.getRealmAccess() != null) {
+            for (String roleName : token.getRealmAccess().getRoles()) {
+                RoleModel role = realm.getRole(roleName);
+                if (role == null) {
+                    throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid realm role " + roleName);
+                }
+                if (!user.hasRole(role)) {
+                    throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for realm role: " + roleName);
+                }
+                if (!client.hasScope(role)) {
+                    throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Client no longer has realm scope: " + roleName);
+                }
             }
         }
-
-        if (resourceRolesRequested.size() > 0) {
-            for (List<RoleModel> roles : resourceRolesRequested.values()) {
-                for (RoleModel role : roles) {
-                    addComposites(token, role);
+        if (token.getResourceAccess() != null) {
+            for (Map.Entry<String, AccessToken.Access> entry : token.getResourceAccess().entrySet()) {
+                ApplicationModel app = realm.getApplicationByName(entry.getKey());
+                if (app == null) {
+                    throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Application no longer exists", "Application no longer exists: " + app.getName());
                 }
+                for (String roleName : entry.getValue().getRoles()) {
+                    RoleModel role = app.getRole(roleName);
+                    if (role == null) {
+                        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", "Unknown application role: " + roleName);
+                    }
+                    if (!user.hasRole(role)) {
+                        throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for application role " + roleName);
+                    }
+                    if (clientApp != null && !clientApp.equals(app) && !client.hasScope(role)) {
+                        throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Client no longer has application scope" + roleName);
+                    }
+                }
+
             }
         }
-        return token;
     }
 
     public void initClaims(IDToken token, ClientModel model, UserModel user) {
@@ -363,7 +344,8 @@ public class TokenManager {
         }
 
         public AccessTokenResponseBuilder generateAccessToken(String scopeParam, ClientModel client, UserModel user, UserSessionModel session) {
-            accessToken = createClientAccessToken(scopeParam, realm, client, user, session);
+            Set<RoleModel> requestedRoles = getAccess(scopeParam, client, user);
+            accessToken = createClientAccessToken(requestedRoles, realm, client, user, session);
             return this;
         }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java b/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java
index c843fbe..06a0e1a 100755
--- a/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java
+++ b/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java
@@ -157,32 +157,22 @@ public class OAuthFlows {
 
         if (!isResource) {
             accessCode.resetExpiration();
-            List<RoleModel> realmRolesRequested = new LinkedList<RoleModel>();
-            MultivaluedMap<String, RoleModel> appRolesRequested = new MultivaluedMapImpl<String, RoleModel>();
-            if (accessCode.getToken().getRealmAccess() != null) {
-                if (accessCode.getToken().getRealmAccess().getRoles() != null) {
-                    for (String role : accessCode.getToken().getRealmAccess().getRoles()) {
-                        RoleModel roleModel = realm.getRole(role);
-                        if (roleModel != null) realmRolesRequested.add(roleModel);
-                    }
-                }
-            }
-            if (accessCode.getToken().getResourceAccess().size() > 0) {
-                for (Map.Entry<String, AccessToken.Access> entry : accessCode.getToken().getResourceAccess().entrySet()) {
-                    ApplicationModel app = realm.getApplicationByName(entry.getKey());
-                    if (app == null) continue;
-                    if (entry.getValue().getRoles() != null) {
-                        for (String role : entry.getValue().getRoles()) {
-                            RoleModel roleModel = app.getRole(role);
-                            if (roleModel != null) appRolesRequested.add(entry.getKey(), roleModel);
-                        }
-
-                    }
+
+            List<RoleModel> realmRoles = new LinkedList<RoleModel>();
+            MultivaluedMap<String, RoleModel> resourceRoles = new MultivaluedMapImpl<String, RoleModel>();
+            for (RoleModel r : accessCode.getRequestedRoles()) {
+                if (r.getContainer() instanceof RealmModel) {
+                    realmRoles.add(r);
+                } else {
+                    resourceRoles.add(((ApplicationModel) r.getContainer()).getName(), r);
                 }
             }
-            return Flows.forms(this.session, realm, uriInfo).setAccessCode(accessCode.getCode()).
-                    setAccessRequest(realmRolesRequested, appRolesRequested).
-                    setClient(client).createOAuthGrant();
+
+            return Flows.forms(this.session, realm, uriInfo)
+                    .setAccessCode(accessCode.getCode())
+                    .setAccessRequest(realmRoles, resourceRoles)
+                    .setClient(client)
+                    .createOAuthGrant();
         }
 
         if (redirect != null) {
diff --git a/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java b/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java
index 85eabf5..1a03dc5 100755
--- a/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java
@@ -227,7 +227,7 @@ public class RequiredActionsService {
         // Password reset through email won't have an associated session
         if (accessCode.getSessionState() == null) {
             UserSessionModel userSession = session.sessions().createUserSession(realm, session.users().getUserById(accessCode.getUser().getId(), realm), clientConnection.getRemoteAddr());
-            accessCode.getToken().setSessionState(userSession.getId());
+            accessCode.setSessionState(userSession.getId());
             audit.session(userSession);
         }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/TokenService.java b/services/src/main/java/org/keycloak/services/resources/TokenService.java
index dc7c937..ef32859 100755
--- a/services/src/main/java/org/keycloak/services/resources/TokenService.java
+++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java
@@ -23,6 +23,7 @@ import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
@@ -641,14 +642,6 @@ public class TokenService {
             return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
                     .build();
         }
-        if (!accessCode.getToken().isActive()) {
-            Map<String, String> res = new HashMap<String, String>();
-            res.put(OAuth2Constants.ERROR, "invalid_grant");
-            res.put(OAuth2Constants.ERROR_DESCRIPTION, "Token expired");
-            audit.error(Errors.INVALID_CODE);
-            return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
-                    .build();
-        }
 
         audit.user(accessCode.getUser());
         audit.session(accessCode.getSessionState());
@@ -698,8 +691,20 @@ public class TokenService {
 
         userSession.associateClient(client);
 
+        AccessToken token = tokenManager.createClientAccessToken(accessCode.getRequestedRoles(), realm, client, user, userSession);
+
+        try {
+            tokenManager.verifyAccess(token, realm, client, user);
+        } catch (OAuthErrorException e) {
+            Map<String, String> error = new HashMap<String, String>();
+            error.put(OAuth2Constants.ERROR, e.getError());
+            if (e.getDescription() != null) error.put(OAuth2Constants.ERROR_DESCRIPTION, e.getDescription());
+            audit.error(Errors.INVALID_CODE);
+            return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
+        }
+
         AccessTokenResponse res = tokenManager.responseBuilder(realm, client, audit)
-                .accessToken(accessCode.getToken())
+                .accessToken(token)
                 .generateIDToken()
                 .generateRefreshToken().build();
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
index f43d735..b40c37f 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
@@ -101,7 +101,7 @@ public class AdapterTest {
             TokenManager tm = new TokenManager();
             UserModel admin = session.users().getUserByUsername("admin", adminRealm);
             UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, null);
-            AccessToken token = tm.createClientAccessToken(null, adminRealm, adminConsole, admin, userSession);
+            AccessToken token = tm.createClientAccessToken(tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession);
             return tm.encodeToken(adminRealm, token);
         } finally {
             keycloakRule.stopSession(session, true);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java
index f3da0af..7c155fb 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java
@@ -88,7 +88,7 @@ public class RelativeUriAdapterTest {
             TokenManager tm = new TokenManager();
             UserModel admin = session.users().getUserByUsername("admin", adminRealm);
             UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, null);
-            AccessToken token = tm.createClientAccessToken(null, adminRealm, adminConsole, admin, userSession);
+            AccessToken token = tm.createClientAccessToken(tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession);
             adminToken = tm.encodeToken(adminRealm, token);
 
         }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java
index 416cc3d..54f85e2 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java
@@ -80,7 +80,7 @@ public class AdminAPITest {
             TokenManager tm = new TokenManager();
             UserModel admin = session.users().getUserByUsername("admin", adminRealm);
             UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, null);
-            AccessToken token = tm.createClientAccessToken(null, adminRealm, adminConsole, admin, userSession);
+            AccessToken token = tm.createClientAccessToken(tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession);
             return tm.encodeToken(adminRealm, token);
         } finally {
             keycloakRule.stopSession(session, true);