diff --git a/apps/webapp/src/app/api/auth/callback/route.ts b/apps/webapp/src/app/api/auth/callback/route.ts index beb11a0..92f8715 100644 --- a/apps/webapp/src/app/api/auth/callback/route.ts +++ b/apps/webapp/src/app/api/auth/callback/route.ts @@ -1,5 +1,15 @@ import { NextRequest, NextResponse } from 'next/server'; +function authentikBase(url?: string | null) { + if (!url) return null; + try { + const parsed = new URL(url); + return parsed.origin.replace(/\/$/, ''); + } catch { + return null; + } +} + export async function GET(req: NextRequest) { const { searchParams, origin } = new URL(req.url); const code = searchParams.get('code'); @@ -11,13 +21,13 @@ export async function GET(req: NextRequest) { const clientSecret = process.env.AUTHENTIK_CLIENT_SECRET; const redirectUri = `${process.env.NEXT_PUBLIC_BASE_URL ?? origin}/api/auth/callback`; - const issuer = issuerRaw?.replace(/\/application\/o\/authorize\/?$/, '').replace(/\/$/, ''); + const authentikHost = authentikBase(issuerRaw); - if (!issuer || !clientId || !clientSecret) { + if (!authentikHost || !clientId || !clientSecret) { return NextResponse.redirect(`${origin}/login?error=oidc_not_configured`); } - const tokenRes = await fetch(`${issuer}/application/o/token/`, { + const tokenRes = await fetch(`${authentikHost}/application/o/token/`, { method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ diff --git a/apps/webapp/src/app/login/page.tsx b/apps/webapp/src/app/login/page.tsx index a200cee..ec7db47 100644 --- a/apps/webapp/src/app/login/page.tsx +++ b/apps/webapp/src/app/login/page.tsx @@ -3,23 +3,28 @@ import { useState } from 'react'; import { useRouter } from 'next/navigation'; -function normalizeIssuer(url?: string | null) { +function authentikBase(url?: string | null) { if (!url) return null; - return url.replace(/\/application\/o\/authorize\/?$/, '').replace(/\/$/, ''); + try { + const parsed = new URL(url); + return parsed.origin.replace(/\/$/, ''); + } catch { + return null; + } } function authentikUrl() { - const issuer = normalizeIssuer(process.env.NEXT_PUBLIC_AUTHENTIK_ISSUER); + const baseHost = authentikBase(process.env.NEXT_PUBLIC_AUTHENTIK_ISSUER); const clientId = process.env.NEXT_PUBLIC_AUTHENTIK_CLIENT_ID; const base = process.env.NEXT_PUBLIC_BASE_URL ?? (typeof window !== 'undefined' ? window.location.origin : ''); - if (!issuer || !clientId) return null; + if (!baseHost || !clientId) return null; const params = new URLSearchParams({ response_type: 'code', client_id: clientId, redirect_uri: `${base}/api/auth/callback`, scope: 'openid email profile', }); - return `${issuer}/application/o/authorize/?${params}`; + return `${baseHost}/application/o/authorize/?${params}`; } export default function LoginPage() {