diff --git a/app/routes/auth/login/page.tsx b/app/routes/auth/login/page.tsx index c414413..2568c64 100644 --- a/app/routes/auth/login/page.tsx +++ b/app/routes/auth/login/page.tsx @@ -8,7 +8,9 @@ import Code from "~/components/code"; import Input from "~/components/input"; import Link from "~/components/link"; import { appConfigContext, authContext, oidcContext } from "~/server/context"; +import type { OidcError, OidcService } from "~/server/oidc/provider"; import { useLiveData } from "~/utils/live-data"; +import log from "~/utils/log"; import type { Route } from "./+types/page"; import { loginAction } from "./action"; @@ -30,12 +32,20 @@ export async function loader({ request, context, url }: Route.LoaderArgs) { const urlState = qp.get("s") ?? undefined; const oidcService = oidc.state === "enabled" ? oidc.value : undefined; - const oidcStatus = oidcService - ? await oidcService.discover().then( - (r) => (r.ok ? oidcService.status() : oidcService.status()), - () => oidcService.status(), - ) - : undefined; + let oidcStatus: ReturnType | undefined; + if (oidcService) { + try { + const result = await oidcService.discover(); + if (!result.ok) { + logLoginOidcError("OIDC discovery failed", result.error); + } + } catch (error) { + log.error("auth", "OIDC discovery failed unexpectedly: %s", String(error)); + log.debug("auth", "OIDC discovery error details: %o", error); + } + + oidcStatus = oidcService.status(); + } if ( oidcService && @@ -59,6 +69,13 @@ export async function loader({ request, context, url }: Route.LoaderArgs) { export const action = loginAction; +function logLoginOidcError(context: string, error: OidcError): void { + log.error("auth", "%s [%s]: %s", context, error.code, error.message); + if (error.hint) { + log.error("auth", "Hint: %s", error.hint); + } +} + export default function Page({ loaderData, actionData }: Route.ComponentProps) { const { isCookieSecureEnabled, isOidcConnectorEnabled, oidcErrorCodes, urlState } = loaderData; diff --git a/app/routes/auth/oidc-callback.ts b/app/routes/auth/oidc-callback.ts index 52b90b2..01b494f 100644 --- a/app/routes/auth/oidc-callback.ts +++ b/app/routes/auth/oidc-callback.ts @@ -7,6 +7,7 @@ import { headscaleContext, oidcContext, } from "~/server/context"; +import { logOidcError } from "~/server/oidc/provider"; import { findHeadscaleUserBySubject } from "~/server/web/headscale-identity"; import { Roles } from "~/server/web/roles"; import log from "~/utils/log"; @@ -27,6 +28,7 @@ export async function loader({ request, context, url }: Route.LoaderArgs) { const service = oidc.value; if (url.searchParams.toString().length === 0) { + log.warn("auth", "Called OIDC callback without query parameters"); return redirect("/login?s=error_no_query"); } @@ -53,10 +55,7 @@ export async function loader({ request, context, url }: Route.LoaderArgs) { const result = await service.handleCallback(url.searchParams, flowState); if (!result.ok) { - log.error("auth", "OIDC callback failed [%s]: %s", result.error.code, result.error.message); - if (result.error.hint) { - log.error("auth", "Hint: %s", result.error.hint); - } + logOidcError("OIDC callback failed", result.error); return redirect("/login?s=error_auth_failed"); } diff --git a/app/routes/auth/oidc-start.ts b/app/routes/auth/oidc-start.ts index 05685f2..41a1208 100644 --- a/app/routes/auth/oidc-start.ts +++ b/app/routes/auth/oidc-start.ts @@ -1,6 +1,7 @@ import { data, redirect } from "react-router"; import { appConfigContext, authContext, oidcContext } from "~/server/context"; +import { logOidcError } from "~/server/oidc/provider"; import { createOidcStateCookie } from "~/utils/oidc-state"; import type { Route } from "./+types/oidc-start"; @@ -22,6 +23,7 @@ export async function loader({ request, context }: Route.LoaderArgs) { const result = await service.startFlow(); if (!result.ok) { + logOidcError("OIDC start failed", result.error); return redirect(`/login?s=${result.error.code}`); } diff --git a/app/server/oidc/provider.ts b/app/server/oidc/provider.ts index 1f3dd43..74fa1e7 100644 --- a/app/server/oidc/provider.ts +++ b/app/server/oidc/provider.ts @@ -75,6 +75,13 @@ export interface OidcError { hint?: string; } +export function logOidcError(context: string, error: OidcError): void { + log.error("auth", "%s [%s]: %s", context, error.code, error.message); + if (error.hint) { + log.error("auth", "Hint: %s", error.hint); + } +} + type JwksResolver = ( protectedHeader?: JWSHeaderParameters, token?: FlattenedJWSInput,