/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at opensso/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id: FSLogoutUtil.java,v 1.12 2008/11/10 22:56:58 veiming Exp $
*
* Portions Copyrighted 2015 ForgeRock AS.
*/
/**
* Utility class for single logout.
*/
public class FSLogoutUtil {
static {
};
/**
* Destroys the principal's session.
* In order to destroy the user's session the following things need
* to be done
* 1. Destroy the Federation Session cookie (eg. iPlanetDirectoryPro)
* 2. Clean the Session manager (FSSessionManager related API call)
* @param userID the principal whose session needs to be destroyed
* @param metaAlias the hostedProvider's meta alias.
* @param sessionIndex Session Index of the user session.
* @param request HTTP Request Object.
* @param response HTTP Response Object.
* @return <code>true</code> if session cleanup was successful;
* <code>false</code> otherwise.
*/
protected static boolean destroyPrincipalSession(
{
}
if (sessionObjList == null) {
return false;
}
// Invalidate all such session ids
// session manager cleanup
if (sessionIndex != null &&
{
}
// clean FSSession map
+ userID);
}
return true;
}
/**
* Destroys local session.
* @param ssoToken session of the principal
* @return <code>true</code> if the local session is deleted;
* <code>false</code> otherwise.
*/
{
try{
}
return true;
} catch (SessionException e){
"SessionException in destroyLocalSession", e);
}
return false;
}
}
/**
* Destroys the principal's session information
* maintained by <code>FSSessionManager</code>.
* @param sessionObjList the Vector of <code>sessionId</code>s
* @param request <code>HttpServletRequest</code> object
* @param response <code>HttpServletResponse</code> object
*/
{
" Active Session exists");
}
try {
} catch (SessionException se) {
"Couldn't obtain session provider:", se);
return;
}
+ sessionId);
}
//Invalidate session
try {
}
"Completed Destroying token for sessionID :" +
}
} catch (SessionException e) {
sessionId + " - ", e);
continue;
}
}
}
} else {
}
}
/**
* Gets the list of the principal's active sessionID
* that is maintained by <code>FSSessionManager</code>.
* @param userDn the principal whose session needs to be destroyed
* @param metaAlias the hosted Entity doing logout cleanup
* @param sessionIndex index of the user's session
* @return Vector list of active Session IDs
*/
{
userDn);
}
synchronized (sessionMgr) {
if (sessionList != null){
if (sessionIndex != null &&
{
return destroySessObj;
}
}
}
return retList;
} else {
return null;
}
}
}
/**
* Cleans the <code>FSSessionManager</code> maintained session
* for the given principal, provider Id and removes all references to
* the provider since logout notification has already been sent to
* that provider.
* @param userDN the principal whose session needs to be destroyed
* @param currentEntityId the provider to whom logout notification is
* about to be sent
* @param metaAlias the hostedProvider doing logout cleanup
* @param session Liberty session.
*/
public static void cleanSessionMapPartnerList(
{
}
}
/**
* Cleans the FSSessionManager maintained session for the given principal,
* provider Id and removes all references to the provider since logout
* notification has already been sent to that provider.
* @param userDN the principal whose session needs to be destroyed
* @param currentEntityId the provider to whom logout notification is
* about to be sent
* @param the hostedProvider doing logout cleanup
*/
/*
protected static void cleanSessionWithNoPartners(
String userDN,
String currentEntityId,
String metaAlias)
{
FSSessionManager sessionMgr =
FSSessionManager.getInstance(metaAlias);
synchronized (sessionMgr) {
List sessionList = sessionMgr.getSessionList(userDN);
if (sessionList != null){
FSUtils.debug.message("Session list is not null");
Iterator iter = sessionList.iterator();
FSSession sessionObj;
while (iter.hasNext()){
sessionObj = (FSSession)iter.next();
if ((sessionObj.getSessionPartners()).isEmpty()) {
sessionMgr.removeSession(userDN, sessionObj);
}
}
} else {
FSUtils.debug.message("Session list is null");
}
}
}
*/
/**
* Cleans the <code>FSSessionManager</code> maintained session
* for the given principal. Logout notification has already been sent to all
* providers that had live connections for this user
* If <code>FSSession</code> is null, then it cleans up the user's all
* sessions.
* @param userDn the principal whose session needs to be destroyed
* @param metaAlias the hostedProvider doing logout cleanup
* @param session Liberty session.
* @return <code>true</code> if session map cleaning was successful;
* <code>false</code> otherwise.
*/
protected static boolean cleanSessionMap(
{
synchronized (sessionMgr) {
} else {
}
}
return true;
}
/**
* Retrieves the session token from the Http Request, and
* validates the token with the OpenAM session manager.
* @param request <code>HTTPServletRequest</code> object containing the
* session cookie information
* @return session token if request contained valid
* session info; <code>false</code> otherwise.
*/
try {
"session is not valid,redirecting for authentication");
return null;
}
return ssoToken;
} catch (SessionException e){
e);
}
return null;
}
}
/**
* Returns the <code>FSAccountFedInfo</code> object for the given
* principal and provider Id.
* @param userID principal whose working account we want to retrieve
* @param entityID the provider Id to whom logout notification needs to
* be sent
* @param metaAlias hosted provider's meta alias
* @return account object for the given user, provider
*/
{
try {
if (metaManager != null) {
try {
if ((accountInfo != null) &&
{
return accountInfo;
}
}
} else {
"WorkingAccount: No affiliations");
}
}
}
}
"getCurrentWorkingAccount after readAccountFedInfo");
}
return acctInfo;
} else {
return null;
}
} catch (Exception e) {
" readAccountFedInfo failed", e);
}
return null;
}
/**
* Returns the information for the given principal and one of the live
* including <code>sessionIndex</code>, provider Id etc.
* @param userID principal who needs to be logged out
* @param metaAlias the hostedProvider doing logout cleanup
* @return HashMap information about live connection provider
*/
{
}
{
}
{
userID);
}
try {
}
return providerMap;
} else {
"FSLogoutUtil.getCurrentProvider:"+
"No more session partners");
}
return null;
}
}
return null;
} catch(Exception e) {
" in getting the current provider", e);
return null;
}
}
/**
* Finds out the role of the provider in live connection list
* @param userID principal who needs to be logged out
* @param entityId to whom logout notification needs to be sent
* @param metaAlias the hostedProvider performing logout
* @return <code>true</code> if provider has IDP role;
* <code>false</code> otherwise.
*/
/*
public static boolean getCurrentProviderRole(
String userID,
String entityId,
String metaAlias)
{
if (FSUtils.debug.messageEnabled()) {
FSUtils.debug.message("Entered getCurrentProviderRole" +
" for user : " + userID);
}
FSSessionManager sessionMgr = FSSessionManager.getInstance(
metaAlias);
synchronized(sessionMgr) {
List sessionList = sessionMgr.getSessionList(userID);
if (sessionList != null) {
FSUtils.debug.message("sessionList is not null");
Iterator iSessionIter = sessionList.iterator();
FSSession currentSession;
while (iSessionIter.hasNext()) {
currentSession = (FSSession)iSessionIter.next();
List providerList = currentSession.getSessionPartners();
Iterator iProviderIter = providerList.iterator();
while (iProviderIter.hasNext()) {
FSSessionPartner sessionPartner =
(FSSessionPartner)iProviderIter.next();
if (sessionPartner.isEquals(entityId)) {
return sessionPartner.getIsRoleIDP();
}
}
}
} else {
FSUtils.debug.message("sessionList is null");
return false;
}
}
return false;
}
*/
/**
* Finds out if there is at least one more partner who should be notified
* of logout
* @param userID principal who needs to be logged out
* @param metaAlias ther provider performing logout
* @return <code>true</code> if any provider exists; <code>false</code>
* otherwise.
*/
public static boolean liveConnectionsExist(
{
userID);
}
synchronized(sessionMgr) {
while (iSessionIter.hasNext()) {
continue;
} else {
return true;
}
}
return false;
} else {
return false;
}
}
}
/**
* Cleans the <code>FSSessionManager</code> maintained session
* information for the user for the given list of sessions.
* @param userID principal who needs to be logged out
* @param sessionList is the list of session Ids to be cleaned for the user
* @param metaAlias the provider performing logout
* @return always return <code>true</code>
*/
protected static boolean cleanSessionMapProviders(
{
if (sessionList != null) {
}
null);
}
}
return true;
}
/**
* Returns the list of all providers who want to be
* notified of logout using HTTP GET profile.
* @param userID principal who needs to be logged out
* @param entityId current provider who uses HTTP GET profile for logout
* @param sessionIndex for the current provider
* @param realm the realm in which the provider resides
* @param metaAlias the hosted provider performing logout
* @return HashMap list of providers who indicate preference to be notified
* of logout using GET profile
*/
{
try {
"Entered FSLogoutUtil::getLogoutGETProviders");
synchronized(sessionMgr) {
while (iSessionIter.hasNext()) {
continue;
} else {
while (iPartnerIter.hasNext()) {
// Only SP can specify GET profile for logout
if (!sessionPartner.getIsRoleIDP()){
realm, curEntityId);
{
{
{
"provider " +
" Added for GET");
}
}
}
}
}
}
}
}
} else {
"Session List is empty, returning " +
"current provider from getLogoutGETProviders");
}
}
return retMap;
}
} catch(IDFFMetaException e){
" getLogoutGETProviders", e);
return null;
}
}
/**
* Determines the user name from the logout request.
* @param reqLogout the logout rerquest received
* @param realm the realm under which the entity resides
* @param hostedEntityId the hosted provider performing logout
* @param hostedRole the role of the hosted provider
* @param hostedConfig extended meta config for hosted provider
* @param metaAlias hosted provider's meta alias
* @return user id if the user is found; <code>null</code> otherwise.
*/
{
try {
", entityID : " + hostedEntityId);
}
} catch (FSAccountMgmtException fe) {
" get account manager:" + fe);
return null;
}
try {
// User Name needs to be figured from logout request
}
}
if ((associatedDomain == null) ||
{
}
// Get userDN
// for SP, search local domain first, for IDP, search
// remote domain(SP) first
acctkey = new FSAccountFedInfoKey(
} else {
acctkey = new FSAccountFedInfoKey(
}
// could not find userDN, search using other domain
// for backward compitability
} else {
acctkey = new FSAccountFedInfoKey(
}
}
return null;
}
}
return userID;
} catch(FSAccountMgmtException e) {
return null;
}
}
/*
* when the user has closed his browser without actually performing a
* logout.
* @param token the session token used to identify the user's
* session
* @param metaAlias the hosted provider performing logout
*/
public static void removeTokenFromSession(
{
try {
} catch (SessionException e) {
"SessionException in removeTokenFromSession", e);
}
return;
}
univId);
}
if (currentSession != null) {
}
}
/**
* Builds signed logout response.
* @param retURL logout return url
* @param bArgStatus logout status
* @param minorVersion minor version of the response should be set to
* @param hostedConfig hosted provider's extended meta
* @param hostedEntityId hosted provider's entity id
* @param userID user id
* @return signed logout response in string format
*/
int minorVersion,
{
try {
// If userID exists read ReturnManager
// If manager has entry use that ResponseTo field else default
}
if (providerMap != null) {
relayState = (String)
" from return list");
}
} else {
}
} else {
}
// Sign the request querystring
if (FSServiceUtils.isSigningOn()) {
"FSLogoutUtil::buildSignedResponse:" +
"couldn't obtain this site's cert alias.");
}
throw new SAMLResponderException(
}
}
} else {
}
redirectURL.toString());
}
return redirectURL.toString();
} catch (Exception e) {
return null;
}
}
/**
* Determines the return location and redirects based on
* logout Return URL of the provider that sent the logout request.
*/
protected static void returnToSource(
int minorVersion,
{
try {
if (remoteDescriptor != null) {
}
return;
} else {
retURL);
}
userID);
return;
}
}
return;
} catch(IOException exx) {
}
}
/**
* Returns the hosted provider's failure page to the user.
* @param request the <code>HttpServletRequest</code> object
* @param response the <code>HttpServletResponse</code> object
* @param providerAlias the provider alias corresponding to the hosted
* provider
*/
{
try {
if (metaManager != null) {
if (hostedEntityId != null &&
{
} else if (hostedEntityId != null &&
{
}
} else {
char delimiter;
} else {
}
}
return;
} else {
return;
}
} catch(IOException ex) {
"FSSingleLogoutServlet: IOException caught:", ex);
return;
}catch(IDFFMetaException e) {
"FSSingleLogoutServlet:IDFFMetaException:", e);
return;
}
}
/**
* Removes current session partner from the session partner list.
*
* @param metaAlias meta alias of the hosted provider
* @param remoteEntityId id of the remote provider
* @param ssoToken session object of the principal who presently login
* @param userID id of the principal
*/
public static void removeCurrentSessionPartner(
{
", userID=" + userID);
}
}
/**
* Returns true if this is IDP initiated profiles, false otherwise.
* @param profile profile to be checked.
* @return true if specified profile is IDP initiated, false otherwise.
*/
+ profile);
}
return true;
} else {
return false;
}
}
}