diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ApplicationResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ApplicationResource.java index 510ce752981..458135c0957 100755 --- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ApplicationResource.java +++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ApplicationResource.java @@ -1,8 +1,10 @@ package org.keycloak.admin.client.resource; +import org.jboss.resteasy.annotations.cache.NoCache; import org.keycloak.representations.idm.ApplicationRepresentation; import org.keycloak.representations.idm.ClaimRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; +import org.keycloak.representations.idm.UserSessionRepresentation; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -12,7 +14,10 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; +import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -84,6 +89,16 @@ public interface ApplicationResource { @Path("logout-user/{username}") public void logoutUser(@PathParam("username") String username); + @Path("session-count") + @GET + @Produces(MediaType.APPLICATION_JSON) + public Map getApplicationSessionCount(); + + @Path("user-sessions") + @GET + @Produces(MediaType.APPLICATION_JSON) + public List getUserSessions(@QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults); + @POST @Path("push-revocation") public void pushRevocation(); diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OpenIDConnectService.java b/services/src/main/java/org/keycloak/protocol/oidc/OpenIDConnectService.java index f0cc1a71d81..0781c0473d4 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/OpenIDConnectService.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/OpenIDConnectService.java @@ -29,6 +29,7 @@ import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; +import org.keycloak.models.UserSessionProvider; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessTokenResponse; @@ -321,9 +322,16 @@ public class OpenIDConnectService { String scope = form.getFirst(OAuth2Constants.SCOPE); - UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "oauth_credentials", false); + UserSessionProvider sessions = session.sessions(); + + UserSessionModel userSession = sessions.createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "oauth_credentials", false); event.session(userSession); + ClientSessionModel clientSession = sessions.createClientSession(realm, client); + clientSession.setAuthMethod(OpenIDConnect.LOGIN_PROTOCOL); + + TokenManager.attachClientSession(userSession, clientSession); + AccessTokenResponse res = tokenManager.responseBuilder(realm, client, event) .generateAccessToken(scope, client, user, userSession) .generateRefreshToken() diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ApplicationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ApplicationTest.java index 61a1b9d067e..2135e096614 100644 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ApplicationTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ApplicationTest.java @@ -1,9 +1,23 @@ package org.keycloak.testsuite.admin; +import org.junit.Rule; import org.junit.Test; +import org.keycloak.admin.client.resource.ApplicationResource; +import org.keycloak.models.ApplicationModel; +import org.keycloak.models.RealmModel; import org.keycloak.representations.idm.ApplicationRepresentation; +import org.keycloak.representations.idm.UserSessionRepresentation; +import org.keycloak.services.managers.RealmManager; +import org.keycloak.testsuite.OAuthClient; +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.util.List; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** @@ -11,6 +25,15 @@ import static org.junit.Assert.assertTrue; */ public class ApplicationTest extends AbstractClientTest { + @Rule + public WebRule webRule = new WebRule(this); + + @WebResource + protected WebDriver driver; + + @WebResource + protected OAuthClient oauth; + @Test public void getApplications() { assertNames(realm.applications().findAll(), "account", "realm-management", "security-admin-console"); @@ -42,6 +65,23 @@ public class ApplicationTest extends AbstractClientTest { assertTrue(rep.isEnabled()); } + @Test + public void getApplicationSessions() throws Exception { + OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", "test-user@localhost", "password"); + assertEquals(200, response.getStatusCode()); + OAuthClient.AuthorizationCodeResponse codeResponse = oauth.doLogin("test-user@localhost", "password"); + + OAuthClient.AccessTokenResponse response2 = oauth.doAccessTokenRequest(codeResponse.getCode(), "password"); + assertEquals(200, response2.getStatusCode()); + + ApplicationResource app = keycloak.realm("test").applications().get("test-app"); + + assertEquals(2, (long) app.getApplicationSessionCount().get("count")); + + List userSessions = app.getUserSessions(0, 100); + assertEquals(2, userSessions.size()); + assertEquals(1, userSessions.get(0).getApplications().size()); + } }