Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

CAS's approach to single sign out is to store the service url ticket of each service the user logs into during a single sign on session, along with the service ticket used to authenticate the user. When that user then browses to the CAS logout page, the CAS server sends an https form post to each service url with a security assertion containing the service ticket for the user. CAS clients are then expected to parse the logout assertion and destroy the local session for that user.

Sign Out Example

In this example, a user has used CAS to authenticate to two web applications, WebApp1 and WebApp2. CAS has set one TGT representing the user's single sign on session, and set a TGT cookie on the user's browser. CAS has also recorded two service ticket and url entries for the webapps. The webapps have created two local sessions for the user, and are also storing the service ticket. These sessions are set on the user's browser, providing their authenticated access to the application. The two webapps have somewhat different client configurations:

  • WebApp1: This webapp has mechanisms allowing server code to modify session objects not associated with the current http request. The service ticket used to authenticate the user is stored in the session object.
  • WebApp2: This webapp does not have the ability to edit or destroy session objects not associated with the current http request. This module has instead implemented an authentication cache of service tickets that are consulted on each page request by looking up a cache entry from session variables.

Phase 1

The user either browses to or is redirected to the CAS Logout page. At this point, all credentials, cookies, and sessions are valid.
Image Added

Phase 2

CAS receives the logout request from the user and begins the single sign out process:

  1. CAS sends a logout form post to the url used as a service url when the user authenticated to WebApp1. This form post is a saml assertion indicating a session should be expired and contains the service ticket the user was issued when authenticating to the application.
  2. WebApp1 receives the request, parses it and looks up the session containing the corresponding service ticket. Once found, it deletes the session. Although the user still has the session set on the browser, future requests to this webapp will result in a redirection to CAS for login.
  3. CAS sends a logout form post to the url used as a service url when the user authenticated to WebApp1. This form post is a saml assertion indicating a session should be expired and contains the service ticket the user was issued when authenticating to the application.
  4. WebApp2 receives the request, parses it and destroys the cache entry containing the corresponding service ticket. Although the user and application still share the session any future requests to this webapp will involve a check of the authentication cache. This check will fail, causing the webapp to delete the session and redirect the user to CAS for authentication.
  5. CAS renders the logout page to the user's browser, including a header deleting the CAS TGT cookie.
  6. The user is now logged out from CAS and all webapps logged into during the CAS single sign on session.
    Image Added

Supporting Single Sign Out in Applications

In order for a client application to support single sign out, it must store the service ticket used to authenticate the user along with the local authentication session. It must then be able to access that service ticket from any http request so the local session can be deleted. In practice this means that the client application must either allow programmatic access to all sessions, or the client must implement a shared cache of authentication credentials that are consulted on each page request.

Code Block
titlepseudocode implementation

// Step 1: Check for existence of a LogoutRequest form post
if(post.LogoutRequest != null){
	serviceTicket = XMLSearch("samlp:LogoutRequest/samlp:SessionIndex");
	if (serviceTicket != null)
		deleteSessionAndCacheEntry(serviceTicket);
}

//Step 2: Normal CAS process - check for service ticket on URL
if(url.ticket != null) {
	HTTPResponse = HTTPGet(CAS_SERVER_URL+VALIDATION_PATH+"?ticket="+url.ticket+"&service="+SERVICE_URL);	
	userID = XMLSearch("cas:serviceResponse/cas:authenticationSuccess/cas:user");
	if(userID != null){
		createSessionAndCacheEntry(url.ticket,userID);
		redirect(SERVICE_URL);
	}
	else {
		redirectToCASforAuthentication();	
	}
}
//Step 3: Normal CAS process - check for session
else if(session.ID != null) {
	AuthUser = validateSessionAndCacheEntry(session.ID);
	if(AuthUser != null) {
		request.AuthUser = AuthUser;	
	}
	else {
		deleteSessionAndCacheEntry(session.ID);
		redirectToCASforAuthentication();	
	}
}
//Step 4: Normal CAS process - redirect for authentication
else {
	redirectToCASforAuthentication();	
}