diff --git a/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java b/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java index 913028ced2..9a827c140e 100755 --- a/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java +++ b/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java @@ -173,7 +173,7 @@ public class ClientSessionCode throw new IllegalArgumentException(); } - return timestamp + lifespan > Time.currentTime(); + return lifespan > Time.currentTime() - timestamp; } public boolean isValidAction(String requestedAction) { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/login/LoginTimeoutValidationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/login/LoginTimeoutValidationTest.java new file mode 100644 index 0000000000..913a9cd841 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/login/LoginTimeoutValidationTest.java @@ -0,0 +1,126 @@ +/* + * Copyright 2019 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.login; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.TargetsContainer; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import org.keycloak.admin.client.resource.UserResource; +import org.keycloak.models.ClientModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.RealmModel; +import org.keycloak.models.UserManager; +import org.keycloak.models.UserModel; +import org.keycloak.models.UserSessionModel; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.services.managers.AuthenticationManager; +import org.keycloak.services.managers.ClientSessionCode; +import org.keycloak.sessions.CommonClientSessionModel; +import org.keycloak.sessions.AuthenticationSessionModel; + +import org.keycloak.testsuite.AbstractTestRealmKeycloakTest; +import org.keycloak.testsuite.arquillian.annotation.ModelTest; +import org.keycloak.testsuite.runonserver.RunOnServerDeployment; + +import static org.keycloak.testsuite.arquillian.DeploymentTargetModifier.AUTH_SERVER_CURRENT; + +public class LoginTimeoutValidationTest extends AbstractTestRealmKeycloakTest { + + @Deployment + @TargetsContainer(AUTH_SERVER_CURRENT) + public static WebArchive deploy() { + return RunOnServerDeployment.create(UserResource.class, LoginTimeoutValidationTest.class) + .addPackages(true, + "org.keycloak.testsuite", + "org.keycloak.testsuite.model"); + } + + + @Override + public void configureTestRealm(RealmRepresentation testRealm) { + + } + + + @Before + public void before() { + testingClient.server().run( session -> { + RealmModel realm = session.realms().getRealmByName("test"); + realm = session.realms().getRealm("test"); + session.users().addUser(realm, "user1"); + }); + } + + + @After + public void after() { + testingClient.server().run( session -> { + RealmModel realm = session.realms().getRealmByName("test"); + session.sessions().removeUserSessions(realm); + UserModel user1 = session.users().getUserByUsername("user1", realm); + + UserManager um = new UserManager(session); + if (user1 != null) { + um.removeUser(realm, user1); + } + }); + } + + + @Test + @ModelTest + public void testIsLoginTimeoutValid(KeycloakSession keycloakSession) { + + RealmModel realm = keycloakSession.realms().getRealmByName("test"); + UserSessionModel userSession = + keycloakSession.sessions().createUserSession( + realm, + keycloakSession.users().getUserByUsername("user1", realm), + "user1", "127.0.0.1", "form", true, null, null + ); + ClientModel client = realm.getClientByClientId("account"); + AuthenticationSessionModel authSession = keycloakSession.authenticationSessions().createRootAuthenticationSession(realm) + .createAuthenticationSession(client); + ClientSessionCode clientSessionCode = new ClientSessionCode(keycloakSession, realm, authSession); + + /* + * KEYCLOAK-10636 Large Login timeout causes login failure + * realm > Realm setting > Tokens > Login timeout + */ + int accessCodeLifespanLoginOrig = realm.getAccessCodeLifespanLogin(); // Login timeout + realm.setAccessCodeLifespanLogin(Integer.MAX_VALUE); + Assert.assertTrue("Login validataion with large Login Timeout failed", + clientSessionCode.isActionActive(ClientSessionCode.ActionType.LOGIN)); + realm.setAccessCodeLifespanLogin(accessCodeLifespanLoginOrig); + + /* + * KEYCLOAK-10637 Large Login Action timeout causes login failure + * realm > Realm setting > Tokens > Login Action timeout + */ + int accessCodeLifespanUserActionOrig = realm.getAccessCodeLifespanUserAction(); // Login Action timeout + realm.setAccessCodeLifespanUserAction(Integer.MAX_VALUE); + Assert.assertTrue("Login validataion with large Login Action Timeout failed", + clientSessionCode.isActionActive(ClientSessionCode.ActionType.USER)); + realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserActionOrig); + } +}