Invoke the Session Management Endpoint for OpenID Connect
The session management endpoint enables OpenID Connect Relying Parties to monitor the login status of a user with a particular OpenID Connect Provider (OP) while minimizing network traffic. With the help of the session management endpoint, a Relying Party (RP) can log out a user who logged out of the OpenID Connect Provider.
The OP session management endpoint URL is obtained from the check_session_iframe attribute in the discovery information that is returned from the discovery endpoint of the OP. This URL must be used as the target of an iframe in the RP application that requires session management functionality. The RP application must also know the id attribute of the iframe in order to submit Window.postMessage() requests to it.
To help determine the login status of a user, the RP loads an iframe with its src target set to the session management endpoint of the OP. The session management endpoint has access to a cookie that stores the login status, or browser state, of a user. This browser state cookie is updated when a user logs out of the OP. The RP can then use client side scripting to invoke the Window.postMessage() function of the OP iframe, sending the client ID and the currently known session state in the text of the message. If the RP receives a postMessage back from the OP frame with a value of changed, then the login status of the user at the OP has changed and the RP can decide whether to log out the user. If a value of unchanged is returned, the user is still logged in at the OP.
A Liberty server with OpenID Connect enabled has access to the OpenID Connect session management endpoint at the following URL:
https://server.example.com:443/oidc/endpoint/<provider_name>/check_session_iframe
Avoid trouble: If we are using an outbound proxy, note that the OpenID Connect RP does not provide a means to route requests through a proxy host automatically.
If we must use a proxy to access the OpenID Connect Provider (OP), the value that you enter for any OP-related URL property must contain the proxy host and port, not the external OP host and port.
In most cases, we can replace the OP host and port with the proxy host and port. The URL that you enter must be visible to both the RP and client (browser or application). For further guidance on how to determine the correct URL to use, contact your proxy administrator.
In this example, the client expects the SSL port to be set to 443.
- Create a web resource in an appropriate RP application capable of loading an
iframe that targets the OP session management endpoint. The web resource also needs
to have access to the session state value that is returned in the session_state
parameter of the authorization response. The session state value can be stored in a cookie, for
example, or in any other way that allows client-side scripting in the web resource to know what the
value is. The following is a sample HTML snippet for such an iframe.
<iframe id="iframeOP" src="https://server.example.com:443/oidc/endpoint/OidcConfigSample/check_session_iframe" frameborder="0" width="0" height="0"></iframe>
- To check the login status of a user, invoke the Window.postMessage() function
of the OP iframe, passing the client ID and session state as the message parameter
in the format Client ID + " " + Session State and the host name of the OP as the
target origin parameter. In the following JavaScript
sample function, the script expects the session state value to be stored in a cookie that is named
session_state, and the getCookieValue() function returns the value
stored in the session_state cookie.
var targetOP = "https://server.example.com:443"; function checkStatus() { var client = "client01"; var sessionState = getCookieValue("session_state"); var text = client + " " + sessionState; var iframe = document.getElementById("iframeOP"); iframe.contentWindow.postMessage(text, targetOP); } - Configure the web resource to listen for postMessages from the OP that contain
the value changed or unchanged to reflect
the respective login status of the user. The RP can then decide whether to log the user out of the
RP based on the value that is returned from the OP. The function must ensure that the origin of the
postMessage matches the expected OP host name. Any messages that do not match are
rejected. The following JavaScript example shows how to
add an event listener to the web resource to listen for such messages.
var targetOP = "https://server.example.com:443"; window.addEventListener("message", receiveMessage, false); function receiveMessage(event) { if (event.origin !== targetOP) { // Origin did not come from the OP; this message must be rejected. return; } if (event.data === "unchanged") { // User is still logged in to the OP } else { // User has logged out of the OP } }
Example
The following HTML example shows a complete HTML page that uses OpenID Connect Session Management. The src attribute of the OP iframe is set to the session management endpoint URL obtained from the OP. The startChecking() function is automatically called every 60 seconds and checks the login status of the user. The page has a message event listener that calls the receiveMessage() function when a postMessage is received. This function makes sure the postMessage comes from the expected domain for the OP and checks the value of the returned message to see whether the login status of the user is changed or unchanged. We can load this HTML page, itself, as an invisible iframe in another web resource within the RP. This enables any web resource that loads this iframe to monitor the login status of the user on the client side.
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>iFrame RP Page</title>
</head>
<body onload="javascript:startChecking()">
<iframe id="iframeOP" src="https://localhost:8999/oidc/endpoint/OidcConfigSample/check_session_iframe" frameborder="0" width="0" height="0"></iframe>
</body>
<script>
var targetOP = "https://server.example.com:443";
window.addEventListener("message", receiveMessage, false);
function startChecking() { checkStatus();
// Check status every 60 seconds
setInterval("checkStatus()", 1000*60);
}
function getCookieValue(cookieName) { var name = cookieName + "=";
var cookies = document.cookie.split(';');
if (!cookies) { return null;
}
for (var i = 0; i < cookies.length; i++) { var cookie = cookies[i].trim();
if (cookie.indexOf(name) == 0) { return cookie.substring(name.length, cookie.length);
}
return null;
}
function checkStatus() { var client = "client01";
var sessionState = getCookieValue("session_state");
var text = client + " " + sessionState;
var iframe = document.getElementById("iframeOP");
iframe.contentWindow.postMessage(text, targetOP);
}
function receiveMessage(event) { if (event.origin !== targetOP) { // Origin did not come from the OP; this message must be rejected
return;
}
if (event.data === "unchanged") { // User is still logged in to the OP
} else { // User has logged out of the OP
}
}
</script>
</html>