OIDC Session Logout — RP-Initiated and OP-Initiated Logout Mechanisms
In this tutorial, you will learn about OIDC Session Logout. We cover key concepts, practical examples, and best practices to help you master this topic.
OIDC defines two logout mechanisms: RP-initiated logout where a client application triggers logout, and OP-initiated logout where the provider logs the user out of all applications simultaneously.
What You'll Learn
- How RP-initiated logout works with the
end_session_endpoint - How OP-initiated logout uses front-channel and back-channel mechanisms
- How to implement proper logout in your OIDC application
Why It Matters
Improper logout implementation leaves users vulnerable. If your app clears its local session but does not notify the provider, the user's SSO session persists. An attacker with access to the user's computer can re-enter any app without credentials. Proper logout terminates all sessions.
Real-World Use
A user clicks "Logout" on DodaMail. DodaMail redirects to the provider's end_session_endpoint with the ID token hint. The provider clears the SSO session and uses front-channel logout to notify DodaDrive and DodaCalendar via iframes, logging the user out of all services simultaneously.
sequenceDiagram
participant User
participant App as DodaMail (RP)
participant Provider as OIDC Provider
participant App2 as DodaDrive (RP2)
User->>App: Click Logout
App->>Provider: Redirect to end_session_endpoint
Note over Provider: Clear SSO Session
Provider->>App: Front-Channel Logout (iframe)
Provider->>App2: Front-Channel Logout (iframe)
App-->>User: Logged Out
App2-->>User: Logged Out
RP-Initiated Logout
from flask import Flask, redirect, session
import urllib.parse
app = Flask(__name__)
@app.route('/logout')
def logout():
# Build RP-initiated logout URL
end_session_endpoint = "https://accounts.example.com/connect/endsession"
id_token_hint = session.get('id_token')
params = {
"id_token_hint": id_token_hint,
"post_logout_redirect_uri": "https://doda.example.com/logged-out",
"state": "logout-state-abc"
}
logout_url = f"{end_session_endpoint}?{urllib.parse.urlencode(params)}"
# Clear local session
session.clear()
# Redirect to provider for global logout
return redirect(logout_url)
OP-Initiated Logout (Provider Side)
The provider can initiate logout when an admin terminates a session or the user logs out from another app:
# Provider-side logout notification
def handle_op_initiated_logout(user_id, logout_token, client_apps):
"""OP-initiated logout: notify all apps via front-channel or back-channel"""
for client in client_apps:
if client.get('frontchannel_logout_uri'):
# Front-channel: browser loads iframe
send_frontchannel_logout(
client['frontchannel_logout_uri'],
logout_token
)
elif client.get('backchannel_logout_uri'):
# Back-channel: server-to-server request
requests.post(
client['backchannel_logout_uri'],
json={"logout_token": logout_token}
)
Handling Logout Callback
// Front-channel logout handler (loaded in iframe)
async function handleFrontChannelLogout() {
const urlParams = new URLSearchParams(window.location.search);
const logoutToken = urlParams.get('logout_token');
if (logoutToken) {
// Clear all auth data
localStorage.removeItem('access_token');
localStorage.removeItem('id_token');
sessionStorage.clear();
// Notify the main window
window.parent.postMessage('logged_out', '*');
// Respond with a 1x1 transparent GIF
document.write('<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">');
}
}
Common Mistakes
1. Only Clearing Local Session
Clearing the local session without calling the provider's end_session_endpoint leaves the SSO session active. The user can re-enter without credentials.
2. Omitting the id_token_hint
Without the id_token_hint, the provider cannot identify which session to terminate and may show a logout confirmation page instead of logging out immediately.
3. Not Registering post_logout_redirect_uri
The provider validates post_logout_redirect_uri against the registered list. Use an unregistered URI and the provider will reject the redirect.
4. Forgetting to Handle the Logout Token
OP-initiated logout sends a logout token. Your app must validate this token (signature, issuer, expiration) before processing the logout.
5. Not Supporting Both Logout Mechanisms
Support both RP-initiated (user clicks logout in your app) and OP-initiated (provider logs user out) for complete logout coverage.
Practice Questions
- What is RP-initiated logout?
- What is the
id_token_hintused for in logout? - How does OP-initiated logout work?
- What is a front-channel logout URI?
- What is a back-channel logout URI?
Answers
- Logout triggered by the relying party (client application) redirecting to the provider. 2. It tells the provider which session to terminate. 3. The provider sends logout notifications to all active applications when a session ends. 4. A URI loaded in an iframe for browser-based logout notification. 5. A server-to-server endpoint for logout notification without browser involvement.
Challenge
Build a logout coordinator that when triggered from any one of three demo applications, performs RP-initiated logout to the provider, waits for front-channel logout confirmations from all apps, and displays a dashboard showing which apps have acknowledged the logout and which have not.
FAQ
Mini Project
Create a complete logout system with three sample applications sharing the same OIDC provider. Implement RP-initiated logout from each app, OP-initiated logout that triggers when any app logs out, and a session monitor showing real-time logout propagation.
What's Next
- Learn about the check_session_iframe for cross-application session monitoring
- Explore front-channel logout implementation details
- Continue to back-channel logout for server-to-server session termination
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro