/*
* Copyright 2016 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.services.managers;
import javax.ws.rs.core.UriInfo;
import org.jboss.logging.Logger;
import org.keycloak.common.ClientConnection;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.RestartLoginCookie;
import org.keycloak.services.util.CookieHelper;
import org.keycloak.sessions.AuthenticationSessionModel;
import org.keycloak.sessions.StickySessionEncoderProvider;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class AuthenticationSessionManager {
public static final String AUTH_SESSION_ID = "AUTH_SESSION_ID";
private static final Logger log = Logger.getLogger(AuthenticationSessionManager.class);
private final KeycloakSession session;
public AuthenticationSessionManager(KeycloakSession session) {
this.session = session;
}
public AuthenticationSessionModel createAuthenticationSession(RealmModel realm, ClientModel client, boolean browserCookie) {
AuthenticationSessionModel authSession = session.authenticationSessions().createAuthenticationSession(realm, client);
if (browserCookie) {
setAuthSessionCookie(authSession.getId(), realm);
}
return authSession;
}
public String getCurrentAuthenticationSessionId(RealmModel realm) {
return getAuthSessionCookieDecoded(realm);
}
public AuthenticationSessionModel getCurrentAuthenticationSession(RealmModel realm) {
String authSessionId = getAuthSessionCookieDecoded(realm);
return authSessionId==null ? null : session.authenticationSessions().getAuthenticationSession(realm, authSessionId);
}
public void setAuthSessionCookie(String authSessionId, RealmModel realm) {
UriInfo uriInfo = session.getContext().getUri();
String cookiePath = AuthenticationManager.getRealmCookiePath(realm, uriInfo);
boolean sslRequired = realm.getSslRequired().isRequired(session.getContext().getConnection());
StickySessionEncoderProvider encoder = session.getProvider(StickySessionEncoderProvider.class);
String encodedAuthSessionId = encoder.encodeSessionId(authSessionId);
CookieHelper.addCookie(AUTH_SESSION_ID, encodedAuthSessionId, cookiePath, null, null, -1, sslRequired, true);
log.debugf("Set AUTH_SESSION_ID cookie with value %s", encodedAuthSessionId);
}
private String getAuthSessionCookieDecoded(RealmModel realm) {
String cookieVal = CookieHelper.getCookieValue(AUTH_SESSION_ID);
if (cookieVal != null) {
log.debugf("Found AUTH_SESSION_ID cookie with value %s", cookieVal);
StickySessionEncoderProvider encoder = session.getProvider(StickySessionEncoderProvider.class);
String decodedAuthSessionId = encoder.decodeSessionId(cookieVal);
// Check if owner of this authentication session changed due to re-hashing (usually node failover or addition of new node)
String reencoded = encoder.encodeSessionId(decodedAuthSessionId);
if (!reencoded.equals(cookieVal)) {
log.debugf("Route changed. Will update authentication session cookie");
setAuthSessionCookie(decodedAuthSessionId, realm);
}
return decodedAuthSessionId;
} else {
log.debugf("Not found AUTH_SESSION_ID cookie");
return null;
}
}
public void removeAuthenticationSession(RealmModel realm, AuthenticationSessionModel authSession, boolean expireRestartCookie) {
log.debugf("Removing authSession '%s'. Expire restart cookie: %b", authSession.getId(), expireRestartCookie);
session.authenticationSessions().removeAuthenticationSession(realm, authSession);
// expire restart cookie
if (expireRestartCookie) {
ClientConnection clientConnection = session.getContext().getConnection();
UriInfo uriInfo = session.getContext().getUri();
RestartLoginCookie.expireRestartCookie(realm, clientConnection, uriInfo);
}
}
// Check to see if we already have authenticationSession with same ID
public UserSessionModel getUserSession(AuthenticationSessionModel authSession) {
return session.sessions().getUserSession(authSession.getRealm(), authSession.getId());
}
}