Full OIDC logout with id_token_hint for provider session termination
Some checks failed
CI / build (push) Successful in 1m10s
CI / docker (push) Successful in 48s
CI / deploy (push) Has been cancelled

Return the OIDC id_token in the callback response so the frontend can
store it and pass it as id_token_hint to the provider's end-session
endpoint on logout. This lets Authentik (or any OIDC provider) honor
the post_logout_redirect_uri and redirect back to the Cameleer login
page instead of showing the provider's own logout page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-14 16:14:07 +01:00
parent 463cab1196
commit a6f94e8a70
7 changed files with 23 additions and 8 deletions

View File

@@ -66,6 +66,7 @@ export const useAuthStore = create<AuthState>((set, get) => ({
}
const { accessToken, refreshToken, displayName } = data;
localStorage.removeItem('cameleer-oidc-end-session');
localStorage.removeItem('cameleer-oidc-id-token');
const name = displayName ?? username;
persistTokens(accessToken, refreshToken, name);
set({
@@ -93,9 +94,12 @@ export const useAuthStore = create<AuthState>((set, get) => ({
if (error || !data) {
throw new Error('OIDC login failed');
}
const { accessToken, refreshToken, displayName } = data;
const { accessToken, refreshToken, displayName, idToken } = data;
const username = displayName ?? 'oidc-user';
persistTokens(accessToken, refreshToken, username);
if (idToken) {
localStorage.setItem('cameleer-oidc-id-token', idToken);
}
set({
accessToken,
refreshToken,
@@ -137,8 +141,10 @@ export const useAuthStore = create<AuthState>((set, get) => ({
logout: () => {
const endSessionEndpoint = localStorage.getItem('cameleer-oidc-end-session');
const idToken = localStorage.getItem('cameleer-oidc-id-token');
clearTokens();
localStorage.removeItem('cameleer-oidc-end-session');
localStorage.removeItem('cameleer-oidc-id-token');
set({
accessToken: null,
refreshToken: null,
@@ -147,9 +153,10 @@ export const useAuthStore = create<AuthState>((set, get) => ({
isAuthenticated: false,
error: null,
});
if (endSessionEndpoint) {
if (endSessionEndpoint && idToken) {
const postLogoutRedirect = `${window.location.origin}/login`;
const params = new URLSearchParams({
id_token_hint: idToken,
post_logout_redirect_uri: postLogoutRedirect,
});
window.location.href = `${endSessionEndpoint}?${params}`;