mirror of
https://github.com/tale/headplane.git
synced 2026-08-31 17:28:14 +00:00
feat: add support for OIDC logouts
Closes HP-407.
This commit is contained in:
@@ -7,15 +7,35 @@ export async function loader() {
|
||||
}
|
||||
|
||||
export async function action({ request, context }: ActionFunctionArgs<LoadContext>) {
|
||||
let principal: Awaited<ReturnType<typeof context.auth.require>> | undefined;
|
||||
try {
|
||||
await context.auth.require(request);
|
||||
principal = await context.auth.require(request);
|
||||
} catch {
|
||||
redirect("/login");
|
||||
return redirect("/login");
|
||||
}
|
||||
|
||||
// When API key is disabled, we need to explicitly redirect
|
||||
// with a logout state to prevent auto login again.
|
||||
const url = context.config.oidc?.disable_api_key_login ? "/login?s=logout" : "/login";
|
||||
let url = context.config.oidc?.disable_api_key_login ? "/login?s=logout" : "/login";
|
||||
|
||||
// For OIDC sessions, redirect to the provider's RP-initiated logout
|
||||
// endpoint when explicitly enabled, so the upstream IdP session is also
|
||||
// ended. Disabled by default because the post_logout_redirect_uri must be
|
||||
// pre-registered on the IdP — turning this on without registering it would
|
||||
// strand users on the IdP's error page.
|
||||
if (principal?.kind === "oidc" && context.oidc?.useEndSession && context.oidc.service) {
|
||||
const status = context.oidc.service.status();
|
||||
if (status.state !== "ready") {
|
||||
// Trigger discovery if it hasn't happened yet so we can find the
|
||||
// end_session_endpoint without forcing a re-login.
|
||||
await context.oidc.service.discover();
|
||||
}
|
||||
|
||||
const endSessionUrl = context.oidc.service.buildEndSessionUrl(principal.idToken);
|
||||
if (endSessionUrl) {
|
||||
url = endSessionUrl;
|
||||
}
|
||||
}
|
||||
|
||||
return redirect(url, {
|
||||
headers: {
|
||||
|
||||
@@ -66,13 +66,21 @@ export async function loader({ request, context }: Route.LoaderArgs) {
|
||||
log.warn("auth", "Failed to link Headscale user: %s", String(error));
|
||||
}
|
||||
|
||||
// Only persist the id_token when RP-initiated logout is enabled — otherwise
|
||||
// we'd be storing a credential we never use.
|
||||
const idToken = context.oidc?.useEndSession ? identity.idToken : undefined;
|
||||
|
||||
return redirect("/", {
|
||||
headers: {
|
||||
"Set-Cookie": await context.auth.createOidcSession(userId, {
|
||||
name: identity.name,
|
||||
email: identity.email,
|
||||
username: identity.username,
|
||||
}),
|
||||
"Set-Cookie": await context.auth.createOidcSession(
|
||||
userId,
|
||||
{
|
||||
name: identity.name,
|
||||
email: identity.email,
|
||||
username: identity.username,
|
||||
},
|
||||
{ idToken },
|
||||
),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user