keycloak-memoizeit

Details

diff --git a/examples/demo-template/testrealm.json b/examples/demo-template/testrealm.json
index d669e6b..556708e 100755
--- a/examples/demo-template/testrealm.json
+++ b/examples/demo-template/testrealm.json
@@ -167,8 +167,7 @@
             "clientId": "admin-client",
             "enabled": true,
             "publicClient": true,
-            "directGrantsOnly": true,
-            "consentRequired": true
+            "directGrantsOnly": true
         },
         {
             "clientId": "product-sa-client",
diff --git a/examples/js-console/src/main/webapp/index.html b/examples/js-console/src/main/webapp/index.html
index 796aebd..153053b 100644
--- a/examples/js-console/src/main/webapp/index.html
+++ b/examples/js-console/src/main/webapp/index.html
@@ -10,6 +10,7 @@
     <button onclick="refreshToken(9999)">Refresh Token</button>
     <button onclick="refreshToken(30)">Refresh Token (if <30s validity)</button>
     <button onclick="loadProfile()">Get Profile</button>
+    <button onclick="loadUserInfo()">Get User Info</button>
     <button onclick="output(keycloak.tokenParsed)">Show Token</button>
     <button onclick="output(keycloak.refreshTokenParsed)">Show Refresh Token</button>
     <button onclick="output(keycloak.idTokenParsed)">Show ID Token</button>
@@ -35,6 +36,14 @@
         });
     }
 
+    function loadUserInfo() {
+        keycloak.loadUserInfo().success(function(userInfo) {
+            output(userInfo);
+        }).error(function() {
+            output('Failed to load user info');
+        });
+    }
+
     function refreshToken(minValidity) {
         keycloak.updateToken(minValidity).success(function(refreshed) {
             if (refreshed) {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
index f17cc27..f410bec 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
@@ -36,6 +36,7 @@ import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.managers.AppAuthManager;
+import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.resources.Cors;
 import org.keycloak.services.Urls;
 
@@ -117,13 +118,17 @@ public class UserInfoEndpoint {
 
         AccessToken token = null;
         try {
-            token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
+            token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()), true);
         } catch (Exception e) {
             throw new ErrorResponseException(OAuthErrorException.INVALID_GRANT, "Token invalid", Status.FORBIDDEN);
         }
 
         UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
         ClientSessionModel clientSession = session.sessions().getClientSession(token.getClientSession());
+        if (userSession == null || clientSession == null || !AuthenticationManager.isSessionValid(realm, userSession)) {
+            throw new ErrorResponseException(OAuthErrorException.INVALID_GRANT, "Token invalid", Status.FORBIDDEN);
+        }
+
         ClientModel clientModel = realm.getClientByClientId(token.getIssuedFor());
         UserModel userModel = userSession.getUser();
         AccessToken userInfo = new AccessToken();
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
index 6b739ba..11ced77 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
@@ -25,6 +25,7 @@ import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.OAuth2Constants;
+import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.AccessTokenResponse;
@@ -54,8 +55,6 @@ import static org.junit.Assert.assertNotNull;
  */
 public class UserInfoTest {
 
-    private static RealmModel realm;
-
     @ClassRule
     public static KeycloakRule keycloakRule = new KeycloakRule();
 
@@ -89,6 +88,27 @@ public class UserInfoTest {
     }
 
     @Test
+    public void testSessionExpired() throws Exception {
+        Client client = ClientBuilder.newClient();
+        UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
+        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+        WebTarget grantTarget = client.target(grantUri);
+        AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(grantTarget);
+
+        KeycloakSession session = keycloakRule.startSession();
+        keycloakRule.startSession().sessions().removeUserSessions(session.realms().getRealm("test"));
+        keycloakRule.stopSession(session, true);
+
+        Response response = executeUserInfoRequest(accessTokenResponse.getToken());
+
+        assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus());
+
+        response.close();
+
+        client.close();
+    }
+
+    @Test
     public void testUnsuccessfulUserInfoRequest() throws Exception {
         Response response = executeUserInfoRequest("bad");