Add expiration field to root authentication session
This commit is contained in:
parent
f8ded02bef
commit
e493b08fa7
15 changed files with 86 additions and 51 deletions
|
@ -36,7 +36,7 @@ import org.keycloak.models.sessions.infinispan.events.RealmRemovedSessionEvent;
|
||||||
import org.keycloak.models.sessions.infinispan.events.SessionEventsSenderTransaction;
|
import org.keycloak.models.sessions.infinispan.events.SessionEventsSenderTransaction;
|
||||||
import org.keycloak.models.sessions.infinispan.stream.RootAuthenticationSessionPredicate;
|
import org.keycloak.models.sessions.infinispan.stream.RootAuthenticationSessionPredicate;
|
||||||
import org.keycloak.models.sessions.infinispan.util.InfinispanKeyGenerator;
|
import org.keycloak.models.sessions.infinispan.util.InfinispanKeyGenerator;
|
||||||
import org.keycloak.models.utils.RealmInfoUtil;
|
import org.keycloak.models.utils.SessionExpiration;
|
||||||
import org.keycloak.sessions.AuthenticationSessionCompoundId;
|
import org.keycloak.sessions.AuthenticationSessionCompoundId;
|
||||||
import org.keycloak.sessions.AuthenticationSessionProvider;
|
import org.keycloak.sessions.AuthenticationSessionProvider;
|
||||||
import org.keycloak.sessions.RootAuthenticationSessionModel;
|
import org.keycloak.sessions.RootAuthenticationSessionModel;
|
||||||
|
@ -83,7 +83,7 @@ public class InfinispanAuthenticationSessionProvider implements AuthenticationSe
|
||||||
entity.setRealmId(realm.getId());
|
entity.setRealmId(realm.getId());
|
||||||
entity.setTimestamp(Time.currentTime());
|
entity.setTimestamp(Time.currentTime());
|
||||||
|
|
||||||
int expirationSeconds = RealmInfoUtil.getDettachedClientSessionLifespan(realm);
|
int expirationSeconds = SessionExpiration.getAuthSessionLifespan(realm);
|
||||||
tx.put(cache, id, entity, expirationSeconds, TimeUnit.SECONDS);
|
tx.put(cache, id, entity, expirationSeconds, TimeUnit.SECONDS);
|
||||||
|
|
||||||
return wrap(realm, entity);
|
return wrap(realm, entity);
|
||||||
|
|
|
@ -31,7 +31,7 @@ import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.sessions.infinispan.entities.AuthenticationSessionEntity;
|
import org.keycloak.models.sessions.infinispan.entities.AuthenticationSessionEntity;
|
||||||
import org.keycloak.models.sessions.infinispan.entities.RootAuthenticationSessionEntity;
|
import org.keycloak.models.sessions.infinispan.entities.RootAuthenticationSessionEntity;
|
||||||
import org.keycloak.models.utils.RealmInfoUtil;
|
import org.keycloak.models.utils.SessionExpiration;
|
||||||
import org.keycloak.sessions.AuthenticationSessionModel;
|
import org.keycloak.sessions.AuthenticationSessionModel;
|
||||||
import org.keycloak.sessions.RootAuthenticationSessionModel;
|
import org.keycloak.sessions.RootAuthenticationSessionModel;
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ public class RootAuthenticationSessionAdapter implements RootAuthenticationSessi
|
||||||
}
|
}
|
||||||
|
|
||||||
void update() {
|
void update() {
|
||||||
int expirationSeconds = RealmInfoUtil.getDettachedClientSessionLifespan(realm);
|
int expirationSeconds = SessionExpiration.getAuthSessionLifespan(realm);
|
||||||
provider.tx.replace(cache, entity.getId(), entity, expirationSeconds, TimeUnit.SECONDS);
|
provider.tx.replace(cache, entity.getId(), entity, expirationSeconds, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,11 +48,14 @@ public class HotRodRootAuthenticationSessionEntity extends AbstractHotRodEntity
|
||||||
@ProtoField(number = 3)
|
@ProtoField(number = 3)
|
||||||
public String realmId;
|
public String realmId;
|
||||||
|
|
||||||
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
|
|
||||||
@ProtoField(number = 4)
|
@ProtoField(number = 4)
|
||||||
public Integer timestamp;
|
public Integer timestamp;
|
||||||
|
|
||||||
|
@ProtoDoc("@Field(index = Index.YES, store = Store.YES)")
|
||||||
@ProtoField(number = 5)
|
@ProtoField(number = 5)
|
||||||
|
public Long expiration;
|
||||||
|
|
||||||
|
@ProtoField(number = 6)
|
||||||
public Set<HotRodAuthenticationSessionEntity> authenticationSessions;
|
public Set<HotRodAuthenticationSessionEntity> authenticationSessions;
|
||||||
|
|
||||||
public static abstract class AbstractHotRodRootAuthenticationSessionEntityDelegate extends UpdatableHotRodEntityDelegateImpl<HotRodRootAuthenticationSessionEntity> implements MapRootAuthenticationSessionEntity {
|
public static abstract class AbstractHotRodRootAuthenticationSessionEntityDelegate extends UpdatableHotRodEntityDelegateImpl<HotRodRootAuthenticationSessionEntity> implements MapRootAuthenticationSessionEntity {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.utils.SessionExpiration;
|
||||||
import org.keycloak.sessions.AuthenticationSessionModel;
|
import org.keycloak.sessions.AuthenticationSessionModel;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -57,6 +58,7 @@ public class MapRootAuthenticationSessionAdapter extends AbstractRootAuthenticat
|
||||||
@Override
|
@Override
|
||||||
public void setTimestamp(int timestamp) {
|
public void setTimestamp(int timestamp) {
|
||||||
entity.setTimestamp(timestamp);
|
entity.setTimestamp(timestamp);
|
||||||
|
entity.setExpiration(SessionExpiration.getAuthSessionExpiration(realm, timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -90,6 +92,7 @@ public class MapRootAuthenticationSessionAdapter extends AbstractRootAuthenticat
|
||||||
|
|
||||||
// Update our timestamp when adding new authenticationSession
|
// Update our timestamp when adding new authenticationSession
|
||||||
entity.setTimestamp(timestamp);
|
entity.setTimestamp(timestamp);
|
||||||
|
entity.setExpiration(SessionExpiration.getAuthSessionExpiration(realm, timestamp));
|
||||||
|
|
||||||
return entity.getAuthenticationSession(tabId).map(this::toAdapter).map(this::setAuthContext).orElse(null);
|
return entity.getAuthenticationSession(tabId).map(this::toAdapter).map(this::setAuthContext).orElse(null);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +104,9 @@ public class MapRootAuthenticationSessionAdapter extends AbstractRootAuthenticat
|
||||||
if (entity.getAuthenticationSessions().isEmpty()) {
|
if (entity.getAuthenticationSessions().isEmpty()) {
|
||||||
session.authenticationSessions().removeRootAuthenticationSession(realm, this);
|
session.authenticationSessions().removeRootAuthenticationSession(realm, this);
|
||||||
} else {
|
} else {
|
||||||
entity.setTimestamp(Time.currentTime());
|
int timestamp = Time.currentTime();
|
||||||
|
entity.setTimestamp(timestamp);
|
||||||
|
entity.setExpiration(SessionExpiration.getAuthSessionExpiration(realm, timestamp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +114,9 @@ public class MapRootAuthenticationSessionAdapter extends AbstractRootAuthenticat
|
||||||
@Override
|
@Override
|
||||||
public void restartSession(RealmModel realm) {
|
public void restartSession(RealmModel realm) {
|
||||||
entity.setAuthenticationSessions(null);
|
entity.setAuthenticationSessions(null);
|
||||||
entity.setTimestamp(Time.currentTime());
|
int timestamp = Time.currentTime();
|
||||||
|
entity.setTimestamp(timestamp);
|
||||||
|
entity.setExpiration(SessionExpiration.getAuthSessionExpiration(realm, timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String generateTabId() {
|
private String generateTabId() {
|
||||||
|
|
|
@ -87,6 +87,9 @@ public interface MapRootAuthenticationSessionEntity extends AbstractEntity, Upda
|
||||||
Integer getTimestamp();
|
Integer getTimestamp();
|
||||||
void setTimestamp(Integer timestamp);
|
void setTimestamp(Integer timestamp);
|
||||||
|
|
||||||
|
Long getExpiration();
|
||||||
|
void setExpiration(Long expiration);
|
||||||
|
|
||||||
Set<MapAuthenticationSessionEntity> getAuthenticationSessions();
|
Set<MapAuthenticationSessionEntity> getAuthenticationSessions();
|
||||||
void setAuthenticationSessions(Set<MapAuthenticationSessionEntity> authenticationSessions);
|
void setAuthenticationSessions(Set<MapAuthenticationSessionEntity> authenticationSessions);
|
||||||
Optional<MapAuthenticationSessionEntity> getAuthenticationSession(String tabId);
|
Optional<MapAuthenticationSessionEntity> getAuthenticationSession(String tabId);
|
||||||
|
|
|
@ -27,12 +27,13 @@ import org.keycloak.models.map.storage.MapKeycloakTransaction;
|
||||||
import org.keycloak.models.map.storage.MapStorage;
|
import org.keycloak.models.map.storage.MapStorage;
|
||||||
import org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator;
|
import org.keycloak.models.map.storage.ModelCriteriaBuilder.Operator;
|
||||||
import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
|
import org.keycloak.models.map.storage.criteria.DefaultModelCriteria;
|
||||||
import org.keycloak.models.utils.RealmInfoUtil;
|
import org.keycloak.models.utils.SessionExpiration;
|
||||||
import org.keycloak.sessions.AuthenticationSessionCompoundId;
|
import org.keycloak.sessions.AuthenticationSessionCompoundId;
|
||||||
import org.keycloak.sessions.AuthenticationSessionProvider;
|
import org.keycloak.sessions.AuthenticationSessionProvider;
|
||||||
import org.keycloak.sessions.RootAuthenticationSessionModel;
|
import org.keycloak.sessions.RootAuthenticationSessionModel;
|
||||||
|
|
||||||
import org.keycloak.sessions.RootAuthenticationSessionModel.SearchableFields;
|
import org.keycloak.sessions.RootAuthenticationSessionModel.SearchableFields;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
@ -63,7 +64,15 @@ public class MapRootAuthenticationSessionProvider implements AuthenticationSessi
|
||||||
private Function<MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> entityToAdapterFunc(RealmModel realm) {
|
private Function<MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> entityToAdapterFunc(RealmModel realm) {
|
||||||
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
|
||||||
|
|
||||||
return origEntity -> new MapRootAuthenticationSessionAdapter(session, realm, origEntity);
|
return origEntity -> {
|
||||||
|
//return new MapRootAuthenticationSessionAdapter(session, realm, origEntity);
|
||||||
|
if (Time.currentTime() < origEntity.getExpiration()) {
|
||||||
|
return new MapRootAuthenticationSessionAdapter(session, realm, origEntity);
|
||||||
|
} else {
|
||||||
|
tx.delete(origEntity.getId());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private Predicate<MapRootAuthenticationSessionEntity> entityRealmFilter(String realmId) {
|
private Predicate<MapRootAuthenticationSessionEntity> entityRealmFilter(String realmId) {
|
||||||
|
@ -89,7 +98,9 @@ public class MapRootAuthenticationSessionProvider implements AuthenticationSessi
|
||||||
MapRootAuthenticationSessionEntity entity = new MapRootAuthenticationSessionEntityImpl();
|
MapRootAuthenticationSessionEntity entity = new MapRootAuthenticationSessionEntityImpl();
|
||||||
entity.setId(id);
|
entity.setId(id);
|
||||||
entity.setRealmId(realm.getId());
|
entity.setRealmId(realm.getId());
|
||||||
entity.setTimestamp(Time.currentTime());
|
int timestamp = Time.currentTime();
|
||||||
|
entity.setTimestamp(timestamp);
|
||||||
|
entity.setExpiration(SessionExpiration.getAuthSessionExpiration(realm, timestamp));
|
||||||
|
|
||||||
if (id != null && tx.read(id) != null) {
|
if (id != null && tx.read(id) != null) {
|
||||||
throw new ModelDuplicateException("Root authentication session exists: " + entity.getId());
|
throw new ModelDuplicateException("Root authentication session exists: " + entity.getId());
|
||||||
|
@ -131,11 +142,9 @@ public class MapRootAuthenticationSessionProvider implements AuthenticationSessi
|
||||||
Objects.requireNonNull(realm, "The provided realm can't be null!");
|
Objects.requireNonNull(realm, "The provided realm can't be null!");
|
||||||
LOG.debugf("Removing expired sessions");
|
LOG.debugf("Removing expired sessions");
|
||||||
|
|
||||||
int expired = Time.currentTime() - RealmInfoUtil.getDettachedClientSessionLifespan(realm);
|
|
||||||
|
|
||||||
DefaultModelCriteria<RootAuthenticationSessionModel> mcb = criteria();
|
DefaultModelCriteria<RootAuthenticationSessionModel> mcb = criteria();
|
||||||
mcb = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
|
mcb = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
|
||||||
.compare(SearchableFields.TIMESTAMP, Operator.LT, expired);
|
.compare(SearchableFields.EXPIRATION, Operator.LT, Time.currentTime());
|
||||||
|
|
||||||
long deletedCount = tx.delete(withCriteria(mcb));
|
long deletedCount = tx.delete(withCriteria(mcb));
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ public class MapFieldPredicates {
|
||||||
put(USER_PREDICATES, UserModel.SearchableFields.SERVICE_ACCOUNT_CLIENT, MapUserEntity::getServiceAccountClientLink);
|
put(USER_PREDICATES, UserModel.SearchableFields.SERVICE_ACCOUNT_CLIENT, MapUserEntity::getServiceAccountClientLink);
|
||||||
|
|
||||||
put(AUTHENTICATION_SESSION_PREDICATES, RootAuthenticationSessionModel.SearchableFields.REALM_ID, MapRootAuthenticationSessionEntity::getRealmId);
|
put(AUTHENTICATION_SESSION_PREDICATES, RootAuthenticationSessionModel.SearchableFields.REALM_ID, MapRootAuthenticationSessionEntity::getRealmId);
|
||||||
put(AUTHENTICATION_SESSION_PREDICATES, RootAuthenticationSessionModel.SearchableFields.TIMESTAMP, MapRootAuthenticationSessionEntity::getTimestamp);
|
put(AUTHENTICATION_SESSION_PREDICATES, RootAuthenticationSessionModel.SearchableFields.EXPIRATION, MapRootAuthenticationSessionEntity::getExpiration);
|
||||||
|
|
||||||
put(AUTHZ_RESOURCE_SERVER_PREDICATES, ResourceServer.SearchableFields.ID, predicateForKeyField(MapResourceServerEntity::getId));
|
put(AUTHZ_RESOURCE_SERVER_PREDICATES, ResourceServer.SearchableFields.ID, predicateForKeyField(MapResourceServerEntity::getId));
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@ import org.keycloak.models.RealmModel;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
public class RealmInfoUtil {
|
public class SessionExpiration {
|
||||||
|
|
||||||
public static int getDettachedClientSessionLifespan(RealmModel realm) {
|
public static int getAuthSessionLifespan(RealmModel realm) {
|
||||||
int lifespan = realm.getAccessCodeLifespanLogin();
|
int lifespan = realm.getAccessCodeLifespanLogin();
|
||||||
if (realm.getAccessCodeLifespanUserAction() > lifespan) {
|
if (realm.getAccessCodeLifespanUserAction() > lifespan) {
|
||||||
lifespan = realm.getAccessCodeLifespanUserAction();
|
lifespan = realm.getAccessCodeLifespanUserAction();
|
||||||
|
@ -35,4 +35,8 @@ public class RealmInfoUtil {
|
||||||
return lifespan;
|
return lifespan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long getAuthSessionExpiration(RealmModel realm, int timestamp) {
|
||||||
|
return (long) timestamp + getAuthSessionLifespan(realm);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -34,7 +34,7 @@ public interface RootAuthenticationSessionModel {
|
||||||
public static class SearchableFields {
|
public static class SearchableFields {
|
||||||
public static final SearchableModelField<RootAuthenticationSessionModel> ID = new SearchableModelField<>("id", String.class);
|
public static final SearchableModelField<RootAuthenticationSessionModel> ID = new SearchableModelField<>("id", String.class);
|
||||||
public static final SearchableModelField<RootAuthenticationSessionModel> REALM_ID = new SearchableModelField<>("realmId", String.class);
|
public static final SearchableModelField<RootAuthenticationSessionModel> REALM_ID = new SearchableModelField<>("realmId", String.class);
|
||||||
public static final SearchableModelField<RootAuthenticationSessionModel> TIMESTAMP = new SearchableModelField<>("timestamp", Long.class);
|
public static final SearchableModelField<RootAuthenticationSessionModel> EXPIRATION = new SearchableModelField<>("expiration", Long.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,6 +57,7 @@ public interface RootAuthenticationSessionModel {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a timestamp when the root authentication session was created or updated.
|
* Sets a timestamp when the root authentication session was created or updated.
|
||||||
|
* It also updates the expiration time for the root authentication session entity.
|
||||||
* @param timestamp {@code int}
|
* @param timestamp {@code int}
|
||||||
*/
|
*/
|
||||||
void setTimestamp(int timestamp);
|
void setTimestamp(int timestamp);
|
||||||
|
|
|
@ -52,6 +52,7 @@ import org.keycloak.testsuite.pages.RegisterPage;
|
||||||
import org.keycloak.testsuite.pages.VerifyEmailPage;
|
import org.keycloak.testsuite.pages.VerifyEmailPage;
|
||||||
import org.keycloak.testsuite.updaters.UserAttributeUpdater;
|
import org.keycloak.testsuite.updaters.UserAttributeUpdater;
|
||||||
import org.keycloak.testsuite.util.GreenMailRule;
|
import org.keycloak.testsuite.util.GreenMailRule;
|
||||||
|
import org.keycloak.testsuite.util.InfinispanTestTimeServiceRule;
|
||||||
import org.keycloak.testsuite.util.MailUtils;
|
import org.keycloak.testsuite.util.MailUtils;
|
||||||
import org.keycloak.testsuite.util.SecondBrowser;
|
import org.keycloak.testsuite.util.SecondBrowser;
|
||||||
import org.keycloak.testsuite.util.UserActionTokenBuilder;
|
import org.keycloak.testsuite.util.UserActionTokenBuilder;
|
||||||
|
@ -91,6 +92,9 @@ public class RequiredActionEmailVerificationTest extends AbstractTestRealmKeyclo
|
||||||
@Rule
|
@Rule
|
||||||
public GreenMailRule greenMail = new GreenMailRule();
|
public GreenMailRule greenMail = new GreenMailRule();
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public InfinispanTestTimeServiceRule ispnTestTimeService = new InfinispanTestTimeServiceRule(this);
|
||||||
|
|
||||||
@Page
|
@Page
|
||||||
protected AppPage appPage;
|
protected AppPage appPage;
|
||||||
|
|
||||||
|
@ -454,7 +458,7 @@ public class RequiredActionEmailVerificationTest extends AbstractTestRealmKeyclo
|
||||||
events.poll();
|
events.poll();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setTimeOffset(3600);
|
setTimeOffset(360);
|
||||||
|
|
||||||
driver.navigate().to(verificationUrl.trim());
|
driver.navigate().to(verificationUrl.trim());
|
||||||
|
|
||||||
|
@ -990,7 +994,7 @@ public class RequiredActionEmailVerificationTest extends AbstractTestRealmKeyclo
|
||||||
String verificationUrl = getPasswordResetEmailLink(message);
|
String verificationUrl = getPasswordResetEmailLink(message);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setTimeOffset(3600);
|
setTimeOffset(360);
|
||||||
|
|
||||||
driver.navigate().to(verificationUrl.trim());
|
driver.navigate().to(verificationUrl.trim());
|
||||||
|
|
||||||
|
|
|
@ -8,13 +8,18 @@ import static org.keycloak.testsuite.broker.BrokerTestTools.getConsumerRoot;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.admin.client.resource.RealmResource;
|
import org.keycloak.admin.client.resource.RealmResource;
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
import org.keycloak.testsuite.util.InfinispanTestTimeServiceRule;
|
||||||
|
|
||||||
public class KcOidcBrokerWithConsentTest extends AbstractInitializedBaseBrokerTest {
|
public class KcOidcBrokerWithConsentTest extends AbstractInitializedBaseBrokerTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public InfinispanTestTimeServiceRule ispnTestTimeService = new InfinispanTestTimeServiceRule(this);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BrokerConfiguration getBrokerConfiguration() {
|
protected BrokerConfiguration getBrokerConfiguration() {
|
||||||
return KcOidcBrokerConfiguration.INSTANCE;
|
return KcOidcBrokerConfiguration.INSTANCE;
|
||||||
|
@ -35,8 +40,8 @@ public class KcOidcBrokerWithConsentTest extends AbstractInitializedBaseBrokerTe
|
||||||
// Change timeouts on realm-with-broker to lower values
|
// Change timeouts on realm-with-broker to lower values
|
||||||
RealmResource realmWithBroker = adminClient.realm(bc.consumerRealmName());
|
RealmResource realmWithBroker = adminClient.realm(bc.consumerRealmName());
|
||||||
RealmRepresentation realmRep = realmWithBroker.toRepresentation();
|
RealmRepresentation realmRep = realmWithBroker.toRepresentation();
|
||||||
realmRep.setAccessCodeLifespanLogin(30);;
|
realmRep.setAccessCodeLifespanLogin(30);
|
||||||
realmRep.setAccessCodeLifespan(30);
|
realmRep.setAccessCodeLifespan(300);
|
||||||
realmRep.setAccessCodeLifespanUserAction(30);
|
realmRep.setAccessCodeLifespanUserAction(30);
|
||||||
realmWithBroker.update(realmRep);
|
realmWithBroker.update(realmRep);
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ import org.keycloak.testsuite.updaters.RealmAttributeUpdater;
|
||||||
import org.keycloak.testsuite.util.AdminClientUtil;
|
import org.keycloak.testsuite.util.AdminClientUtil;
|
||||||
import org.keycloak.testsuite.util.ContainerAssume;
|
import org.keycloak.testsuite.util.ContainerAssume;
|
||||||
import org.keycloak.testsuite.util.DroneUtils;
|
import org.keycloak.testsuite.util.DroneUtils;
|
||||||
|
import org.keycloak.testsuite.util.InfinispanTestTimeServiceRule;
|
||||||
import org.keycloak.testsuite.util.JavascriptBrowser;
|
import org.keycloak.testsuite.util.JavascriptBrowser;
|
||||||
import org.keycloak.testsuite.util.OAuthClient;
|
import org.keycloak.testsuite.util.OAuthClient;
|
||||||
import org.keycloak.testsuite.util.Matchers;
|
import org.keycloak.testsuite.util.Matchers;
|
||||||
|
@ -87,7 +88,6 @@ import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotEquals;
|
import static org.junit.Assert.assertNotEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.keycloak.common.Profile.Feature.AUTHORIZATION;
|
|
||||||
import static org.keycloak.common.Profile.Feature.DYNAMIC_SCOPES;
|
import static org.keycloak.common.Profile.Feature.DYNAMIC_SCOPES;
|
||||||
import static org.keycloak.testsuite.admin.ApiUtil.findClientByClientId;
|
import static org.keycloak.testsuite.admin.ApiUtil.findClientByClientId;
|
||||||
import static org.keycloak.testsuite.util.OAuthClient.AUTH_SERVER_ROOT;
|
import static org.keycloak.testsuite.util.OAuthClient.AUTH_SERVER_ROOT;
|
||||||
|
@ -165,6 +165,9 @@ public class LoginTest extends AbstractTestRealmKeycloakTest {
|
||||||
@Page
|
@Page
|
||||||
protected LoginPasswordUpdatePage updatePasswordPage;
|
protected LoginPasswordUpdatePage updatePasswordPage;
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public InfinispanTestTimeServiceRule ispnTestTimeService = new InfinispanTestTimeServiceRule(this);
|
||||||
|
|
||||||
private static String userId;
|
private static String userId;
|
||||||
|
|
||||||
private static String user2Id;
|
private static String user2Id;
|
||||||
|
@ -762,9 +765,8 @@ public class LoginTest extends AbstractTestRealmKeycloakTest {
|
||||||
@Test
|
@Test
|
||||||
public void loginExpiredCode() {
|
public void loginExpiredCode() {
|
||||||
loginPage.open();
|
loginPage.open();
|
||||||
|
// authSession expired and removed from the storage
|
||||||
setTimeOffset(5000);
|
setTimeOffset(5000);
|
||||||
// No explicitly call "removeExpired". Hence authSession will still exists, but will be expired
|
|
||||||
//testingClient.testing().removeExpired("test");
|
|
||||||
|
|
||||||
loginPage.login("login@test.com", "password");
|
loginPage.login("login@test.com", "password");
|
||||||
loginPage.assertCurrent();
|
loginPage.assertCurrent();
|
||||||
|
@ -772,35 +774,28 @@ public class LoginTest extends AbstractTestRealmKeycloakTest {
|
||||||
Assert.assertEquals("Your login attempt timed out. Login will start from the beginning.", loginPage.getError());
|
Assert.assertEquals("Your login attempt timed out. Login will start from the beginning.", loginPage.getError());
|
||||||
setTimeOffset(0);
|
setTimeOffset(0);
|
||||||
|
|
||||||
events.expectLogin().user((String) null).session((String) null).error(Errors.EXPIRED_CODE).clearDetails()
|
events.expectLogin().client((String) null).user((String) null).session((String) null).error(Errors.EXPIRED_CODE).clearDetails()
|
||||||
.assertEvent();
|
.assertEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
// KEYCLOAK-1037
|
// KEYCLOAK-1037
|
||||||
@Test
|
@Test
|
||||||
public void loginExpiredCodeWithExplicitRemoveExpired() {
|
public void loginExpiredCodeWithExplicitRemoveExpired() {
|
||||||
getTestingClient().testing().setTestingInfinispanTimeService();
|
|
||||||
|
|
||||||
try {
|
|
||||||
loginPage.open();
|
loginPage.open();
|
||||||
setTimeOffset(5000);
|
setTimeOffset(5000);
|
||||||
// Explicitly call "removeExpired". Hence authSession won't exist, but will be restarted from the KC_RESTART
|
|
||||||
testingClient.testing().removeExpired("test");
|
|
||||||
|
|
||||||
loginPage.login("login@test.com", "password");
|
loginPage.login("login@test.com", "password");
|
||||||
|
|
||||||
//loginPage.assertCurrent();
|
|
||||||
loginPage.assertCurrent();
|
loginPage.assertCurrent();
|
||||||
|
|
||||||
Assert.assertEquals("Your login attempt timed out. Login will start from the beginning.", loginPage.getError());
|
Assert.assertEquals("Your login attempt timed out. Login will start from the beginning.", loginPage.getError());
|
||||||
|
|
||||||
|
setTimeOffset(0);
|
||||||
|
|
||||||
events.expectLogin().user((String) null).session((String) null).error(Errors.EXPIRED_CODE).clearDetails()
|
events.expectLogin().user((String) null).session((String) null).error(Errors.EXPIRED_CODE).clearDetails()
|
||||||
.detail(Details.RESTART_AFTER_TIMEOUT, "true")
|
.detail(Details.RESTART_AFTER_TIMEOUT, "true")
|
||||||
.client((String) null)
|
.client((String) null)
|
||||||
.assertEvent();
|
.assertEvent();
|
||||||
} finally {
|
|
||||||
getTestingClient().testing().revertTestingInfinispanTimeService();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -51,6 +51,7 @@ import org.keycloak.testsuite.pages.VerifyEmailPage;
|
||||||
import org.keycloak.testsuite.updaters.ClientAttributeUpdater;
|
import org.keycloak.testsuite.updaters.ClientAttributeUpdater;
|
||||||
import org.keycloak.testsuite.util.BrowserTabUtil;
|
import org.keycloak.testsuite.util.BrowserTabUtil;
|
||||||
import org.keycloak.testsuite.util.GreenMailRule;
|
import org.keycloak.testsuite.util.GreenMailRule;
|
||||||
|
import org.keycloak.testsuite.util.InfinispanTestTimeServiceRule;
|
||||||
import org.keycloak.testsuite.util.MailUtils;
|
import org.keycloak.testsuite.util.MailUtils;
|
||||||
import org.keycloak.testsuite.util.OAuthClient;
|
import org.keycloak.testsuite.util.OAuthClient;
|
||||||
import org.keycloak.testsuite.util.RealmBuilder;
|
import org.keycloak.testsuite.util.RealmBuilder;
|
||||||
|
@ -92,6 +93,9 @@ public class ResetPasswordTest extends AbstractTestRealmKeycloakTest {
|
||||||
private String userId;
|
private String userId;
|
||||||
private UserRepresentation defaultUser;
|
private UserRepresentation defaultUser;
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public InfinispanTestTimeServiceRule ispnTestTimeService = new InfinispanTestTimeServiceRule(this);
|
||||||
|
|
||||||
@Drone
|
@Drone
|
||||||
@SecondBrowser
|
@SecondBrowser
|
||||||
protected WebDriver driver2;
|
protected WebDriver driver2;
|
||||||
|
@ -409,7 +413,7 @@ public class ResetPasswordTest extends AbstractTestRealmKeycloakTest {
|
||||||
String changePasswordUrl = MailUtils.getPasswordResetEmailLink(message);
|
String changePasswordUrl = MailUtils.getPasswordResetEmailLink(message);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setTimeOffset(1800 + 23);
|
setTimeOffset(360);
|
||||||
|
|
||||||
driver.navigate().to(changePasswordUrl.trim());
|
driver.navigate().to(changePasswordUrl.trim());
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,7 @@ public class AuthenticationSessionProviderTest extends AbstractTestRealmKeycloak
|
||||||
public void testLoginSessionsCRUD(KeycloakSession session) {
|
public void testLoginSessionsCRUD(KeycloakSession session) {
|
||||||
AtomicReference<String> rootAuthSessionID = new AtomicReference<>();
|
AtomicReference<String> rootAuthSessionID = new AtomicReference<>();
|
||||||
AtomicReference<String> tabID = new AtomicReference<>();
|
AtomicReference<String> tabID = new AtomicReference<>();
|
||||||
|
final int timestamp = Time.currentTime();
|
||||||
|
|
||||||
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCRUD1) -> {
|
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCRUD1) -> {
|
||||||
KeycloakSession currentSession = sessionCRUD1;
|
KeycloakSession currentSession = sessionCRUD1;
|
||||||
|
@ -107,7 +108,7 @@ public class AuthenticationSessionProviderTest extends AbstractTestRealmKeycloak
|
||||||
tabID.set(authSession.getTabId());
|
tabID.set(authSession.getTabId());
|
||||||
|
|
||||||
authSession.setAction("foo");
|
authSession.setAction("foo");
|
||||||
rootAuthSession.setTimestamp(100);
|
rootAuthSession.setTimestamp(timestamp);
|
||||||
});
|
});
|
||||||
|
|
||||||
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCRUD2) -> {
|
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionCRUD2) -> {
|
||||||
|
@ -121,11 +122,11 @@ public class AuthenticationSessionProviderTest extends AbstractTestRealmKeycloak
|
||||||
AuthenticationSessionModel authSession = rootAuthSession.getAuthenticationSession(client1, tabID.get());
|
AuthenticationSessionModel authSession = rootAuthSession.getAuthenticationSession(client1, tabID.get());
|
||||||
testAuthenticationSession(authSession, client1.getId(), null, "foo");
|
testAuthenticationSession(authSession, client1.getId(), null, "foo");
|
||||||
|
|
||||||
assertThat(rootAuthSession.getTimestamp(), is(100));
|
assertThat(rootAuthSession.getTimestamp(), is(timestamp));
|
||||||
|
|
||||||
// Update and commit
|
// Update and commit
|
||||||
authSession.setAction("foo-updated");
|
authSession.setAction("foo-updated");
|
||||||
rootAuthSession.setTimestamp(200);
|
rootAuthSession.setTimestamp(timestamp + 1000);
|
||||||
authSession.setAuthenticatedUser(currentSession.users().getUserByUsername(realm, "user1"));
|
authSession.setAuthenticatedUser(currentSession.users().getUserByUsername(realm, "user1"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -141,7 +142,7 @@ public class AuthenticationSessionProviderTest extends AbstractTestRealmKeycloak
|
||||||
|
|
||||||
testAuthenticationSession(authSession, client1.getId(), user1.getId(), "foo-updated");
|
testAuthenticationSession(authSession, client1.getId(), user1.getId(), "foo-updated");
|
||||||
|
|
||||||
assertThat(rootAuthSession.getTimestamp(), is(200));
|
assertThat(rootAuthSession.getTimestamp(), is(timestamp + 1000));
|
||||||
|
|
||||||
// Remove and commit
|
// Remove and commit
|
||||||
currentSession.authenticationSessions().removeRootAuthenticationSession(realm, rootAuthSession);
|
currentSession.authenticationSessions().removeRootAuthenticationSession(realm, rootAuthSession);
|
||||||
|
@ -161,6 +162,7 @@ public class AuthenticationSessionProviderTest extends AbstractTestRealmKeycloak
|
||||||
public void testAuthenticationSessionRestart(KeycloakSession session) {
|
public void testAuthenticationSessionRestart(KeycloakSession session) {
|
||||||
AtomicReference<String> parentAuthSessionID = new AtomicReference<>();
|
AtomicReference<String> parentAuthSessionID = new AtomicReference<>();
|
||||||
AtomicReference<String> tabID = new AtomicReference<>();
|
AtomicReference<String> tabID = new AtomicReference<>();
|
||||||
|
final int timestamp = Time.currentTime();
|
||||||
|
|
||||||
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRestart1) -> {
|
KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), (KeycloakSession sessionRestart1) -> {
|
||||||
KeycloakSession currentSession = sessionRestart1;
|
KeycloakSession currentSession = sessionRestart1;
|
||||||
|
@ -176,7 +178,7 @@ public class AuthenticationSessionProviderTest extends AbstractTestRealmKeycloak
|
||||||
tabID.set(authSession.getTabId());
|
tabID.set(authSession.getTabId());
|
||||||
|
|
||||||
authSession.setAction("foo");
|
authSession.setAction("foo");
|
||||||
authSession.getParentSession().setTimestamp(100);
|
authSession.getParentSession().setTimestamp(timestamp);
|
||||||
|
|
||||||
authSession.setAuthenticatedUser(user1);
|
authSession.setAuthenticatedUser(user1);
|
||||||
authSession.setAuthNote("foo", "bar");
|
authSession.setAuthNote("foo", "bar");
|
||||||
|
@ -256,7 +258,7 @@ public class AuthenticationSessionProviderTest extends AbstractTestRealmKeycloak
|
||||||
RealmModel realm = currentSession.realms().getRealm("test");
|
RealmModel realm = currentSession.realms().getRealm("test");
|
||||||
RealmModel fooRealm = currentSession.realms().createRealm("foo-realm");
|
RealmModel fooRealm = currentSession.realms().createRealm("foo-realm");
|
||||||
fooRealm.setDefaultRole(currentSession.roles().addRealmRole(fooRealm, Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + fooRealm.getName()));
|
fooRealm.setDefaultRole(currentSession.roles().addRealmRole(fooRealm, Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + fooRealm.getName()));
|
||||||
|
fooRealm.setAccessCodeLifespanLogin(1800);
|
||||||
fooRealm.addClient("foo-client");
|
fooRealm.addClient("foo-client");
|
||||||
|
|
||||||
authSessionID.set(currentSession.authenticationSessions().createRootAuthenticationSession(realm).getId());
|
authSessionID.set(currentSession.authenticationSessions().createRootAuthenticationSession(realm).getId());
|
||||||
|
|
|
@ -179,8 +179,6 @@ public class AuthenticationSessionTest extends KeycloakModelTest {
|
||||||
Assert.assertNotNull(rootAuthSession);
|
Assert.assertNotNull(rootAuthSession);
|
||||||
|
|
||||||
Time.setOffset(1900);
|
Time.setOffset(1900);
|
||||||
// not needed with Infinispan where expiration handles Infinispan itself
|
|
||||||
session.authenticationSessions().removeExpired(realm);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue