sso session idle and max lifespan
This commit is contained in:
parent
27efd3c0a4
commit
bc2360e985
15 changed files with 86 additions and 64 deletions
|
@ -121,7 +121,7 @@ public class FreeMarkerAccount implements Account {
|
||||||
attributes.put("log", new LogBean(events));
|
attributes.put("log", new LogBean(events));
|
||||||
break;
|
break;
|
||||||
case SESSIONS:
|
case SESSIONS:
|
||||||
attributes.put("sessions", new SessionsBean(sessions));
|
attributes.put("sessions", new SessionsBean(realm, sessions));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/SessionsBean.java
Normal file → Executable file
13
forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/SessionsBean.java
Normal file → Executable file
|
@ -1,5 +1,6 @@
|
||||||
package org.keycloak.account.freemarker.model;
|
package org.keycloak.account.freemarker.model;
|
||||||
|
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.util.Time;
|
import org.keycloak.util.Time;
|
||||||
|
|
||||||
|
@ -13,11 +14,12 @@ import java.util.List;
|
||||||
public class SessionsBean {
|
public class SessionsBean {
|
||||||
|
|
||||||
private List<UserSessionBean> events;
|
private List<UserSessionBean> events;
|
||||||
|
private RealmModel realm;
|
||||||
|
|
||||||
public SessionsBean(List<UserSessionModel> sessions) {
|
public SessionsBean(RealmModel realm, List<UserSessionModel> sessions) {
|
||||||
this.events = new LinkedList<UserSessionBean>();
|
this.events = new LinkedList<UserSessionBean>();
|
||||||
for (UserSessionModel session : sessions) {
|
for (UserSessionModel session : sessions) {
|
||||||
this.events.add(new UserSessionBean(session));
|
this.events.add(new UserSessionBean(realm, session));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,8 +30,10 @@ public class SessionsBean {
|
||||||
public static class UserSessionBean {
|
public static class UserSessionBean {
|
||||||
|
|
||||||
private UserSessionModel session;
|
private UserSessionModel session;
|
||||||
|
private RealmModel realm;
|
||||||
|
|
||||||
public UserSessionBean(UserSessionModel session) {
|
public UserSessionBean(RealmModel realm, UserSessionModel session) {
|
||||||
|
this.realm = realm;
|
||||||
this.session = session;
|
this.session = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +46,8 @@ public class SessionsBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getExpires() {
|
public Date getExpires() {
|
||||||
return Time.toDate(session.getExpires());
|
int max = session.getStarted() + realm.getSsoSessionMaxLifespan();
|
||||||
|
return Time.toDate(max);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
4
model/api/src/main/java/org/keycloak/models/UserSessionModel.java
Normal file → Executable file
4
model/api/src/main/java/org/keycloak/models/UserSessionModel.java
Normal file → Executable file
|
@ -21,8 +21,8 @@ public interface UserSessionModel {
|
||||||
|
|
||||||
void setStarted(int started);
|
void setStarted(int started);
|
||||||
|
|
||||||
int getExpires();
|
int getLastSessionRefresh();
|
||||||
|
|
||||||
void setExpires(int expires);
|
void setLastSessionRefresh(int seconds);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1389,10 +1389,9 @@ public class RealmAdapter implements RealmModel {
|
||||||
entity.setIpAddress(ipAddress);
|
entity.setIpAddress(ipAddress);
|
||||||
|
|
||||||
int currentTime = Time.currentTime();
|
int currentTime = Time.currentTime();
|
||||||
int expires = currentTime + realm.getSsoSessionIdleTimeout();
|
|
||||||
|
|
||||||
entity.setStarted(currentTime);
|
entity.setStarted(currentTime);
|
||||||
entity.setExpires(expires);
|
entity.setLastSessionRefresh(currentTime);
|
||||||
|
|
||||||
em.persist(entity);
|
em.persist(entity);
|
||||||
return new UserSessionAdapter(entity);
|
return new UserSessionAdapter(entity);
|
||||||
|
@ -1429,7 +1428,10 @@ public class RealmAdapter implements RealmModel {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeExpiredUserSessions() {
|
public void removeExpiredUserSessions() {
|
||||||
em.createNamedQuery("removeUserSessionExpired").setParameter("currentTime", Time.currentTime()).executeUpdate();
|
em.createNamedQuery("removeUserSessionExpired")
|
||||||
|
.setParameter("maxTime", Time.currentTime() - getSsoSessionMaxLifespan())
|
||||||
|
.setParameter("idleTime", Time.currentTime() - getSsoSessionIdleTimeout())
|
||||||
|
.executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
9
model/jpa/src/main/java/org/keycloak/models/jpa/UserSessionAdapter.java
Normal file → Executable file
9
model/jpa/src/main/java/org/keycloak/models/jpa/UserSessionAdapter.java
Normal file → Executable file
|
@ -60,13 +60,12 @@ public class UserSessionAdapter implements UserSessionModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getExpires() {
|
public int getLastSessionRefresh() {
|
||||||
return entity.getExpires();
|
return entity.getLastSessionRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExpires(int expires) {
|
public void setLastSessionRefresh(int seconds) {
|
||||||
entity.setExpires(expires);
|
entity.setLastSessionRefresh(seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
13
model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserSessionEntity.java
Normal file → Executable file
13
model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserSessionEntity.java
Normal file → Executable file
|
@ -17,7 +17,7 @@ import javax.persistence.NamedQuery;
|
||||||
@NamedQueries({
|
@NamedQueries({
|
||||||
@NamedQuery(name = "getUserSessionByUser", query = "select s from UserSessionEntity s where s.user = :user"),
|
@NamedQuery(name = "getUserSessionByUser", query = "select s from UserSessionEntity s where s.user = :user"),
|
||||||
@NamedQuery(name = "removeUserSessionByUser", query = "delete from UserSessionEntity s where s.user = :user"),
|
@NamedQuery(name = "removeUserSessionByUser", query = "delete from UserSessionEntity s where s.user = :user"),
|
||||||
@NamedQuery(name = "removeUserSessionExpired", query = "delete from UserSessionEntity s where s.expires < :currentTime")
|
@NamedQuery(name = "removeUserSessionExpired", query = "delete from UserSessionEntity s where s.started < :maxTime or s.lastSessionRefresh < :idleTime")
|
||||||
})
|
})
|
||||||
public class UserSessionEntity {
|
public class UserSessionEntity {
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ public class UserSessionEntity {
|
||||||
|
|
||||||
int started;
|
int started;
|
||||||
|
|
||||||
int expires;
|
int lastSessionRefresh;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
|
@ -67,12 +67,11 @@ public class UserSessionEntity {
|
||||||
this.started = started;
|
this.started = started;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getExpires() {
|
public int getLastSessionRefresh() {
|
||||||
return expires;
|
return lastSessionRefresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setExpires(int expires) {
|
public void setLastSessionRefresh(int lastSessionRefresh) {
|
||||||
this.expires = expires;
|
this.lastSessionRefresh = lastSessionRefresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1356,10 +1356,9 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
||||||
entity.setIpAddress(ipAddress);
|
entity.setIpAddress(ipAddress);
|
||||||
|
|
||||||
int currentTime = Time.currentTime();
|
int currentTime = Time.currentTime();
|
||||||
int expires = currentTime + realm.getSsoSessionIdleTimeout();
|
|
||||||
|
|
||||||
entity.setStarted(currentTime);
|
entity.setStarted(currentTime);
|
||||||
entity.setExpires(expires);
|
entity.setLastSessionRefresh(currentTime);
|
||||||
|
|
||||||
getMongoStore().insertEntity(entity, invocationContext);
|
getMongoStore().insertEntity(entity, invocationContext);
|
||||||
return new UserSessionAdapter(entity, this, invocationContext);
|
return new UserSessionAdapter(entity, this, invocationContext);
|
||||||
|
@ -1398,8 +1397,14 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeExpiredUserSessions() {
|
public void removeExpiredUserSessions() {
|
||||||
|
int currentTime = Time.currentTime();
|
||||||
DBObject query = new QueryBuilder()
|
DBObject query = new QueryBuilder()
|
||||||
.and("expires").lessThan(Time.currentTime())
|
.and("started").lessThan(currentTime - realm.getSsoSessionMaxLifespan())
|
||||||
|
.get();
|
||||||
|
|
||||||
|
getMongoStore().removeEntities(MongoUserSessionEntity.class, query, invocationContext);
|
||||||
|
query = new QueryBuilder()
|
||||||
|
.and("lastSessionRefresh").lessThan(currentTime - realm.getSsoSessionIdleTimeout())
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
getMongoStore().removeEntities(MongoUserSessionEntity.class, query, invocationContext);
|
getMongoStore().removeEntities(MongoUserSessionEntity.class, query, invocationContext);
|
||||||
|
|
8
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserSessionAdapter.java
Normal file → Executable file
8
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserSessionAdapter.java
Normal file → Executable file
|
@ -65,13 +65,13 @@ public class UserSessionAdapter implements UserSessionModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getExpires() {
|
public int getLastSessionRefresh() {
|
||||||
return entity.getExpires();
|
return entity.getLastSessionRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExpires(int expires) {
|
public void setLastSessionRefresh(int seconds) {
|
||||||
entity.setExpires(expires);
|
entity.setLastSessionRefresh(seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
10
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserSessionEntity.java
Normal file → Executable file
10
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserSessionEntity.java
Normal file → Executable file
|
@ -17,7 +17,7 @@ public class MongoUserSessionEntity extends AbstractIdentifiableEntity implement
|
||||||
|
|
||||||
private int started;
|
private int started;
|
||||||
|
|
||||||
private int expires;
|
private int lastSessionRefresh;
|
||||||
|
|
||||||
public String getUser() {
|
public String getUser() {
|
||||||
return user;
|
return user;
|
||||||
|
@ -43,12 +43,12 @@ public class MongoUserSessionEntity extends AbstractIdentifiableEntity implement
|
||||||
this.started = started;
|
this.started = started;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getExpires() {
|
public int getLastSessionRefresh() {
|
||||||
return expires;
|
return lastSessionRefresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setExpires(int expires) {
|
public void setLastSessionRefresh(int lastSessionRefresh) {
|
||||||
this.expires = expires;
|
this.lastSessionRefresh = lastSessionRefresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2,22 +2,13 @@ package org.keycloak.services.managers;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.UnauthorizedException;
|
import org.jboss.resteasy.spi.UnauthorizedException;
|
||||||
import org.keycloak.RSATokenVerifier;
|
|
||||||
import org.keycloak.VerificationException;
|
|
||||||
import org.keycloak.jose.jws.JWSInput;
|
|
||||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.provider.ProviderSession;
|
import org.keycloak.provider.ProviderSession;
|
||||||
import org.keycloak.representations.AccessToken;
|
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.BadRequestException;
|
|
||||||
import javax.ws.rs.core.Cookie;
|
import javax.ws.rs.core.Cookie;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
import javax.ws.rs.core.NewCookie;
|
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -33,6 +24,11 @@ public class AppAuthManager extends AuthenticationManager {
|
||||||
public UserModel authenticateRequest(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
|
public UserModel authenticateRequest(RealmModel realm, UriInfo uriInfo, HttpHeaders headers) {
|
||||||
AuthResult authResult = authenticateIdentityCookie(realm, uriInfo, headers);
|
AuthResult authResult = authenticateIdentityCookie(realm, uriInfo, headers);
|
||||||
if (authResult != null) {
|
if (authResult != null) {
|
||||||
|
Cookie remember = headers.getCookies().get(AuthenticationManager.KEYCLOAK_REMEMBER_ME);
|
||||||
|
boolean rememberMe = remember != null;
|
||||||
|
// refresh the cookies!
|
||||||
|
createLoginCookie(realm, authResult.getUser(), authResult.getSession(), uriInfo, rememberMe);
|
||||||
|
if (rememberMe) createRememberMeCookie(realm, uriInfo);
|
||||||
return authResult.getUser();
|
return authResult.getUser();
|
||||||
} else {
|
} else {
|
||||||
return authenticateBearerToken(realm, uriInfo, headers);
|
return authenticateBearerToken(realm, uriInfo, headers);
|
||||||
|
|
|
@ -61,6 +61,11 @@ public class AuthenticationManager {
|
||||||
this.protector = protector;
|
this.protector = protector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isSessionValid(RealmModel realm, UserSessionModel session) {
|
||||||
|
int currentTime = Time.currentTime();
|
||||||
|
return session == null || session.getLastSessionRefresh() + realm.getSsoSessionIdleTimeout() < currentTime || session.getStarted() + realm.getSsoSessionMaxLifespan() < currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
public AccessToken createIdentityToken(RealmModel realm, UserModel user, UserSessionModel session) {
|
public AccessToken createIdentityToken(RealmModel realm, UserModel user, UserSessionModel session) {
|
||||||
logger.info("createIdentityToken");
|
logger.info("createIdentityToken");
|
||||||
AccessToken token = new AccessToken();
|
AccessToken token = new AccessToken();
|
||||||
|
@ -77,7 +82,7 @@ public class AuthenticationManager {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createLoginCookie(Response.ResponseBuilder builder, RealmModel realm, UserModel user, UserSessionModel session, UriInfo uriInfo, boolean rememberMe) {
|
public void createLoginCookie(RealmModel realm, UserModel user, UserSessionModel session, UriInfo uriInfo, boolean rememberMe) {
|
||||||
logger.info("createLoginCookie");
|
logger.info("createLoginCookie");
|
||||||
String cookiePath = getIdentityCookiePath(realm, uriInfo);
|
String cookiePath = getIdentityCookiePath(realm, uriInfo);
|
||||||
AccessToken identityToken = createIdentityToken(realm, user, session);
|
AccessToken identityToken = createIdentityToken(realm, user, session);
|
||||||
|
@ -97,11 +102,11 @@ public class AuthenticationManager {
|
||||||
sessionCookieValue += "-" + session.getId();
|
sessionCookieValue += "-" + session.getId();
|
||||||
}
|
}
|
||||||
// THIS SHOULD NOT BE A HTTPONLY COOKIE! It is used for OpenID Connect Iframe Session support!
|
// THIS SHOULD NOT BE A HTTPONLY COOKIE! It is used for OpenID Connect Iframe Session support!
|
||||||
builder.cookie(new NewCookie(KEYCLOAK_SESSION_COOKIE, sessionCookieValue, cookiePath, null, null, maxAge, secureOnly));
|
CookieHelper.addCookie(KEYCLOAK_SESSION_COOKIE, sessionCookieValue, cookiePath, null, null, maxAge, secureOnly, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createRememberMeCookie(HttpResponse response, RealmModel realm, UriInfo uriInfo) {
|
public void createRememberMeCookie(RealmModel realm, UriInfo uriInfo) {
|
||||||
String path = getIdentityCookiePath(realm, uriInfo);
|
String path = getIdentityCookiePath(realm, uriInfo);
|
||||||
boolean secureOnly = !realm.isSslNotRequired();
|
boolean secureOnly = !realm.isSslNotRequired();
|
||||||
// remember me cookie should be persistent
|
// remember me cookie should be persistent
|
||||||
|
@ -121,6 +126,7 @@ public class AuthenticationManager {
|
||||||
String path = getIdentityCookiePath(realm, uriInfo);
|
String path = getIdentityCookiePath(realm, uriInfo);
|
||||||
expireCookie(realm, KEYCLOAK_IDENTITY_COOKIE, path, true);
|
expireCookie(realm, KEYCLOAK_IDENTITY_COOKIE, path, true);
|
||||||
expireCookie(realm, KEYCLOAK_SESSION_COOKIE, path, false);
|
expireCookie(realm, KEYCLOAK_SESSION_COOKIE, path, false);
|
||||||
|
expireRememberMeCookie(realm, uriInfo);
|
||||||
}
|
}
|
||||||
public void expireRememberMeCookie(RealmModel realm, UriInfo uriInfo) {
|
public void expireRememberMeCookie(RealmModel realm, UriInfo uriInfo) {
|
||||||
logger.debug("Expiring remember me cookie");
|
logger.debug("Expiring remember me cookie");
|
||||||
|
@ -146,15 +152,9 @@ public class AuthenticationManager {
|
||||||
|
|
||||||
public AuthResult authenticateIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers, boolean checkActive) {
|
public AuthResult authenticateIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers, boolean checkActive) {
|
||||||
logger.info("authenticateIdentityCookie");
|
logger.info("authenticateIdentityCookie");
|
||||||
String cookieName = KEYCLOAK_IDENTITY_COOKIE;
|
Cookie cookie = headers.getCookies().get(KEYCLOAK_IDENTITY_COOKIE);
|
||||||
return authenticateIdentityCookie(realm, uriInfo, headers, cookieName, checkActive);
|
|
||||||
}
|
|
||||||
|
|
||||||
private AuthResult authenticateIdentityCookie(RealmModel realm, UriInfo uriInfo, HttpHeaders headers, String cookieName, boolean checkActive) {
|
|
||||||
logger.info("authenticateIdentityCookie");
|
|
||||||
Cookie cookie = headers.getCookies().get(cookieName);
|
|
||||||
if (cookie == null) {
|
if (cookie == null) {
|
||||||
logger.infov("authenticateCookie could not find cookie: {0}", cookieName);
|
logger.infov("authenticateCookie could not find cookie: {0}", KEYCLOAK_IDENTITY_COOKIE);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +162,9 @@ public class AuthenticationManager {
|
||||||
AuthResult authResult = verifyIdentityToken(realm, uriInfo, checkActive, tokenString);
|
AuthResult authResult = verifyIdentityToken(realm, uriInfo, checkActive, tokenString);
|
||||||
if (authResult == null) {
|
if (authResult == null) {
|
||||||
expireIdentityCookie(realm, uriInfo);
|
expireIdentityCookie(realm, uriInfo);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
authResult.getSession().setLastSessionRefresh(Time.currentTime());
|
||||||
return authResult;
|
return authResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +176,6 @@ public class AuthenticationManager {
|
||||||
logger.info("Checking if identity token is active");
|
logger.info("Checking if identity token is active");
|
||||||
if (!token.isActive() || token.getIssuedAt() < realm.getNotBefore()) {
|
if (!token.isActive() || token.getIssuedAt() < realm.getNotBefore()) {
|
||||||
logger.info("identity cookie expired");
|
logger.info("identity cookie expired");
|
||||||
expireIdentityCookie(realm, uriInfo);
|
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
logger.info("token.isActive() : " + token.isActive());
|
logger.info("token.isActive() : " + token.isActive());
|
||||||
|
@ -195,9 +196,12 @@ public class AuthenticationManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
UserSessionModel session = realm.getUserSession(token.getSessionState());
|
UserSessionModel session = realm.getUserSession(token.getSessionState());
|
||||||
if (session == null || session.getExpires() < Time.currentTime()) {
|
int currentTime = Time.currentTime();
|
||||||
|
if (isSessionValid(realm, session)) {
|
||||||
|
if (session != null) {
|
||||||
|
realm.removeUserSession(session);
|
||||||
|
}
|
||||||
logger.info("User session not active");
|
logger.info("User session not active");
|
||||||
expireIdentityCookie(realm, uriInfo);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,11 @@ public class TokenManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
UserSessionModel session = realm.getUserSession(refreshToken.getSessionState());
|
UserSessionModel session = realm.getUserSession(refreshToken.getSessionState());
|
||||||
if (session == null || session.getExpires() < Time.currentTime()) {
|
int currentTime = Time.currentTime();
|
||||||
|
if (AuthenticationManager.isSessionValid(realm, session)) {
|
||||||
|
if (session != null) {
|
||||||
|
realm.removeUserSession(session);
|
||||||
|
}
|
||||||
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active");
|
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,6 +195,12 @@ public class TokenManager {
|
||||||
AccessToken accessToken = initToken(realm, client, user, session);
|
AccessToken accessToken = initToken(realm, client, user, session);
|
||||||
accessToken.setRealmAccess(refreshToken.getRealmAccess());
|
accessToken.setRealmAccess(refreshToken.getRealmAccess());
|
||||||
accessToken.setResourceAccess(refreshToken.getResourceAccess());
|
accessToken.setResourceAccess(refreshToken.getResourceAccess());
|
||||||
|
|
||||||
|
// only refresh session if next token refresh will be after idle timeout
|
||||||
|
if (currentTime + realm.getAccessTokenLifespan() > session.getLastSessionRefresh() + realm.getSsoSessionIdleTimeout()) {
|
||||||
|
session.setLastSessionRefresh(currentTime);
|
||||||
|
}
|
||||||
|
|
||||||
return accessToken;
|
return accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -408,7 +408,7 @@ public class RequiredActionsService {
|
||||||
AuthenticationManager authManager = new AuthenticationManager(providerSession);
|
AuthenticationManager authManager = new AuthenticationManager(providerSession);
|
||||||
|
|
||||||
UserSessionModel session = realm.getUserSession(accessCode.getSessionState());
|
UserSessionModel session = realm.getUserSession(accessCode.getSessionState());
|
||||||
if (session == null || session.getExpires() < Time.currentTime()) {
|
if (AuthenticationManager.isSessionValid(realm, session)) {
|
||||||
return Flows.oauth(realm, request, uriInfo, authManager, tokenManager).redirectError(accessCode.getClient(), "access_denied", accessCode.getState(), accessCode.getRedirectUri());
|
return Flows.oauth(realm, request, uriInfo, authManager, tokenManager).redirectError(accessCode.getClient(), "access_denied", accessCode.getState(), accessCode.getRedirectUri());
|
||||||
}
|
}
|
||||||
audit.session(session);
|
audit.session(session);
|
||||||
|
|
|
@ -58,7 +58,6 @@ import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.NewCookie;
|
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.SecurityContext;
|
import javax.ws.rs.core.SecurityContext;
|
||||||
import javax.ws.rs.core.UriBuilder;
|
import javax.ws.rs.core.UriBuilder;
|
||||||
|
@ -374,7 +373,7 @@ public class TokenService {
|
||||||
AuthenticationStatus status = authManager.authenticateForm(clientConnection, realm, formData);
|
AuthenticationStatus status = authManager.authenticateForm(clientConnection, realm, formData);
|
||||||
|
|
||||||
if (remember) {
|
if (remember) {
|
||||||
authManager.createRememberMeCookie(response, realm, uriInfo);
|
authManager.createRememberMeCookie(realm, uriInfo);
|
||||||
} else {
|
} else {
|
||||||
authManager.expireRememberMeCookie(realm, uriInfo);
|
authManager.expireRememberMeCookie(realm, uriInfo);
|
||||||
}
|
}
|
||||||
|
@ -636,7 +635,7 @@ public class TokenService {
|
||||||
}
|
}
|
||||||
|
|
||||||
UserSessionModel session = realm.getUserSession(accessCode.getSessionState());
|
UserSessionModel session = realm.getUserSession(accessCode.getSessionState());
|
||||||
if (session == null || session.getExpires() < Time.currentTime()) {
|
if (AuthenticationManager.isSessionValid(realm, session)) {
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
Map<String, String> res = new HashMap<String, String>();
|
||||||
res.put(OAuth2Constants.ERROR, "invalid_grant");
|
res.put(OAuth2Constants.ERROR, "invalid_grant");
|
||||||
res.put(OAuth2Constants.ERROR_DESCRIPTION, "Session not active");
|
res.put(OAuth2Constants.ERROR_DESCRIPTION, "Session not active");
|
||||||
|
@ -915,7 +914,8 @@ public class TokenService {
|
||||||
}
|
}
|
||||||
|
|
||||||
UserSessionModel session = realm.getUserSession(accessCodeEntry.getSessionState());
|
UserSessionModel session = realm.getUserSession(accessCodeEntry.getSessionState());
|
||||||
if (session == null || session.getExpires() < Time.currentTime()) {
|
int currentTime = Time.currentTime();
|
||||||
|
if (AuthenticationManager.isSessionValid(realm, session)) {
|
||||||
audit.error(Errors.INVALID_CODE);
|
audit.error(Errors.INVALID_CODE);
|
||||||
return oauth.forwardToSecurityFailure("Session not active");
|
return oauth.forwardToSecurityFailure("Session not active");
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,9 @@ public class OAuthFlows {
|
||||||
Response.ResponseBuilder location = Response.status(302).location(redirectUri.build());
|
Response.ResponseBuilder location = Response.status(302).location(redirectUri.build());
|
||||||
Cookie remember = request.getHttpHeaders().getCookies().get(AuthenticationManager.KEYCLOAK_REMEMBER_ME);
|
Cookie remember = request.getHttpHeaders().getCookies().get(AuthenticationManager.KEYCLOAK_REMEMBER_ME);
|
||||||
rememberMe = rememberMe || remember != null;
|
rememberMe = rememberMe || remember != null;
|
||||||
authManager.createLoginCookie(location, realm, accessCode.getUser(), session, uriInfo, rememberMe);
|
// refresh the cookies!
|
||||||
|
authManager.createLoginCookie(realm, accessCode.getUser(), session, uriInfo, rememberMe);
|
||||||
|
if (rememberMe) authManager.createRememberMeCookie(realm, uriInfo);
|
||||||
return location.build();
|
return location.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue