ultisuite-client/lib/auth/authentik-user-url.ts
R3D347HR4Y 9ea2d3325d
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat(auth): enhance authentication flows with embedded support and UI improvements
- Updated login and signup components to utilize AuthCard for better user experience during redirection.
- Introduced AuthentikEmbedDialog for seamless integration of Authentik's identity portal within the application.
- Enhanced password recovery and signup flows with dynamic theme handling and improved loading states.
- Refactored existing components to streamline authentication processes and improve maintainability.
2026-06-21 00:12:45 +02:00

131 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* URLs Authentik (portail utilisateur + flows self-service).
* Issuer attendu : `https://host/auth/application/o/<slug>/`.
*/
import { getAuthentikBase } from "@/lib/auth/oidc-config"
import type { MailThemeMode } from "@/lib/mail-settings/types"
export type AuthentikUserSettingsTab =
| "details"
| "sessions"
| "mfa"
| "sources"
const TAB_PAGE: Record<AuthentikUserSettingsTab, string> = {
details: "page-details",
sessions: "page-sessions",
mfa: "page-mfa",
sources: "page-sources",
}
/** Flows Authentik par défaut pour self-service (modifiables côté admin). */
export const AUTHENTIK_SELF_SERVICE_FLOWS = {
enrollment: "ulti-enrollment",
passwordChange: "default-password-change",
recovery: "ulti-recovery",
totpSetup: "default-authenticator-totp-setup",
webauthnSetup: "default-authenticator-webauthn-setup",
staticSetup: "default-authenticator-static-setup",
} as const
export type AuthentikUrlOptions = {
tab?: AuthentikUserSettingsTab
flowSlug?: string
/** Thème Authentik (`?theme=`) aligné sur lapp Ulti. */
theme?: "light" | "dark"
}
function authentikBaseUrl(): string | null {
try {
return getAuthentikBase().replace(/\/$/, "")
} catch {
return null
}
}
function userSettingsHash(tab?: AuthentikUserSettingsTab): string {
if (!tab || tab === "details") return "#/settings"
const page = TAB_PAGE[tab]
const params = encodeURIComponent(JSON.stringify({ page }))
return `#/settings;${params}`
}
function withAuthentikTheme(url: string, theme?: "light" | "dark"): string {
if (!theme) return url
try {
const parsed = new URL(url)
parsed.searchParams.set("theme", theme)
return parsed.toString()
} catch {
return url
}
}
/** Thème effectif pour Authentik à partir des réglages Ulti. */
export function resolveAuthentikTheme(
themeMode: MailThemeMode,
resolvedTheme?: string | null
): "light" | "dark" {
if (themeMode === "light" || themeMode === "dark") return themeMode
if (resolvedTheme === "dark" || resolvedTheme === "light") return resolvedTheme
if (typeof document !== "undefined") {
return document.documentElement.classList.contains("dark") ? "dark" : "light"
}
return "light"
}
function userSettingsPath(tab?: AuthentikUserSettingsTab): string {
const hash = userSettingsHash(tab)
return `/if/user/${hash}`
}
/** Page « Paramètres » du portail utilisateur Authentik. */
export function authentikUserSettingsUrl(
tab: AuthentikUserSettingsTab = "details",
theme?: "light" | "dark"
): string | null {
const base = authentikBaseUrl()
if (!base) return null
return withAuthentikTheme(`${base}${userSettingsPath(tab)}`, theme)
}
/** Flow Authentik (mot de passe, MFA, etc.). */
export function authentikFlowUrl(
flowSlug: string,
theme?: "light" | "dark"
): string | null {
const base = authentikBaseUrl()
const slug = flowSlug.trim().replace(/^\/+|\/+$/g, "")
if (!base || !slug) return null
return withAuthentikTheme(`${base}/if/flow/${slug}/`, theme)
}
export function authentikPasswordChangeFlowUrl(
theme?: "light" | "dark"
): string | null {
return authentikFlowUrl(AUTHENTIK_SELF_SERVICE_FLOWS.passwordChange, theme)
}
export function authentikEnrollmentFlowUrl(
theme?: "light" | "dark"
): string | null {
return authentikFlowUrl(AUTHENTIK_SELF_SERVICE_FLOWS.enrollment, theme)
}
export function authentikRecoveryFlowUrl(
theme?: "light" | "dark"
): string | null {
return authentikFlowUrl(AUTHENTIK_SELF_SERVICE_FLOWS.recovery, theme)
}
/** URL Authentik (flow ou onglet réglages) avec thème. */
export function buildAuthentikUrl(options: AuthentikUrlOptions): string | null {
const { tab, flowSlug, theme } = options
if (flowSlug) {
const flowUrl = authentikFlowUrl(flowSlug, theme)
if (flowUrl) return flowUrl
}
return authentikUserSettingsUrl(tab ?? "details", theme)
}