OIDC Post-Logout Redirect URI — Controlling the Destination After Session Termination
In this tutorial, you will learn about OIDC Post. We cover key concepts, practical examples, and best practices to help you master this topic.
The post_logout_redirect_uri parameter in Openid Connect specifies where the provider redirects the user after successful logout, allowing applications to return users to a specific page instead of a generic provider landing page.
What You'll Learn
- How to configure post-logout redirect URIs in client registration
- How to use the parameter in RP-initiated logout
- Security considerations for preventing open redirect attacks
Why It Matters
Without a post-logout redirect, users land on the provider's generic logout page. This creates a poor user experience and loses the brand context. A properly configured post-logout redirect returns users to your application's goodbye page or login page, maintaining brand continuity.
Real-World Use
A user logs out of DodaBrowser. The provider redirects them to https://doda.example.com/logged-out which displays a friendly message, options to log back in, and links to DodaTech's other products. Without this, the user would see the provider's generic "You are logged out" page.
flowchart LR
A["User clicks\nLogout"] --> B["OIDC Provider\nend_session_endpoint"]
B --> C["Provider clears\nSSO session"]
C --> D["Redirect to\npost_logout_redirect_uri"]
D --> E["https://doda.example.com\n/logged-out"]
E --> F["Show goodbye page\n+ login button"]
style D fill:#dbeafe,stroke:#2563eb
style E fill:#bbf7d0,stroke:#16a34a
Configuring Post-Logout Redirect URIs
Register allowed post-logout redirect URIs during client registration:
{
"client_id": "doda-browser",
"redirect_uris": ["https://doda.example.com/callback"],
"post_logout_redirect_uris": [
"https://doda.example.com/logged-out",
"https://doda.example.com/login"
]
}
Using the Parameter in Logout
from flask import Flask, redirect, session, request
import urllib.parse
app = Flask(__name__)
@app.route('/logout')
def logout():
end_session_endpoint = "https://accounts.example.com/connect/endsession"
id_token = session.get('id_token')
# Build logout URL with post-logout redirect
params = {
"id_token_hint": id_token,
"post_logout_redirect_uri": "https://doda.example.com/logged-out",
"state": "logout-nonce-abc"
}
logout_url = f"{end_session_endpoint}?{urllib.parse.urlencode(params)}"
# Clear local session
session.clear()
return redirect(logout_url)
Handling the Post-Logout Redirect
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/logged-out')
def logged_out():
"""Displayed after successful OIDC logout"""
state = request.args.get('state')
# Verify state matches the one we sent
expected_state = "logout-nonce-abc"
if state != expected_state:
app.logger.warning("Logout state mismatch")
return render_template('logged_out.html', context={
'message': 'You have been successfully logged out.',
'login_url': '/login',
'home_url': '/'
})
<!-- templates/logged_out.html -->
<div class="logout-container">
<h1>You're logged out</h1>
<p>Your session has been terminated successfully.</p>
<p>You have been logged out of all DodaTech applications.</p>
<div class="actions">
<a href="{{ login_url }}" class="button">Log Back In</a>
<a href="{{ home_url }}" class="button secondary">Go to Home</a>
</div>
</div>
Security Validation
Always validate the post_logout_redirect_uri server-side to prevent open redirect attacks:
import re
from flask import Flask, abort
app = Flask(__name__)
ALLOWED_POST_LOGOUT_URIS = [
"https://doda.example.com/logged-out",
"https://doda.example.com/login",
"https://doda.example.com"
]
def validate_post_logout_uri(uri):
"""Validate that the URI is in the allowed list"""
if uri in ALLOWED_POST_LOGOUT_URIS:
return True
# Pattern match for wildcard support
for allowed in ALLOWED_POST_LOGOUT_URIS:
pattern = re.escape(allowed).replace(r'\*', '.*')
if re.match(f"^{pattern}$", uri):
return True
return False
@app.route('/perform-logout')
def perform_logout():
post_logout_uri = request.args.get('post_logout_redirect_uri')
if post_logout_uri and not validate_post_logout_uri(post_logout_uri):
abort(400, "Invalid post-logout redirect URI")
# Proceed with logout
return redirect(post_logout_uri or "https://doda.example.com/logged-out")
Common Mistakes
1. Not Registering Post-Logout URIs
The provider rejects unregistered redirect URIs. Register all allowed post-logout URIs during client registration.
2. Using Open Redirects
Without validation, an attacker can craft a logout URL that redirects to a malicious site. Always validate the redirect URI server-side.
3. Ignoring the State Parameter
The state parameter in the logout request prevents CSRF Attacks on the redirect. Validate it when the redirect arrives.
4. Redirecting to External Domains
Post-logout redirect URIs must be on the same domain or explicitly registered. Do not redirect to third-party domains.
5. Not Handling the Missing Redirect Case
If no post_logout_redirect_uri is specified, the provider shows its own page. Handle this gracefully in your application.
Practice Questions
- What does the
post_logout_redirect_uriparameter do? - Where do you register allowed post-logout redirect URIs?
- Why is redirect URI validation important?
- What is the purpose of the state parameter in logout?
- What happens if you omit
post_logout_redirect_uri?
Answers
- It specifies where the provider redirects after logout. 2. In the client registration metadata (post_logout_redirect_uris). 3. To prevent open redirect attacks that send users to malicious sites. 4. It prevents CSRF attacks on the logout redirect. 5. The provider shows its own generic logout page.
Challenge
Build a logout redirect validator that checks post-logout URIs against a configured whitelist, supports glob patterns, logs violations, and returns a safe default redirect URI when validation fails.
FAQ
Mini Project
Build a logout flow with post-logout redirect handling that includes: a configuration UI for managing allowed redirect URIs, server-side validation with security logging, a branded logged-out page with options to re-authenticate, and support for multiple language versions of the logged-out page.
What's Next
- Review all OIDC concepts in the complete project
- Explore claims mechanisms in the claims request lesson
- Continue to the next API topic: OIDC vs OAuth deep comparison
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro