Files
0pt/app/api/auth/me/route.ts
admin 023406c9b6
CI (SIAX Cloud) / integration (push) Skipped
CI (SIAX Cloud) / sonar (push) Skipped
masterplan-lock / check (push) Successful in 3s
CI (SIAX Cloud) / sonar (pull_request) Skipped
masterplan-lock / check (pull_request) Successful in 5s
Security Scan (SIAX Cloud) / security (push) Successful in 14s
CI (SIAX Cloud) / security (push) Successful in 21s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 19s
CI (SIAX Cloud) / security (pull_request) Successful in 23s
CI (SIAX Cloud) / integration (pull_request) Successful in 28s
CI (SIAX Cloud) / quality (push) Successful in 48s
CI (SIAX Cloud) / quality (pull_request) Successful in 45s
feat(auth): Zitadel OIDC login for the portal
The portal had no way to obtain a verified principal: /api/0pt/* requires a
Bearer token, but the browser only had the dev-only HMAC cookie.

- GET /api/auth/login: Authorization Code + PKCE against Zitadel.
- GET /api/auth/callback: code exchange, id_token verification (issuer,
  audience, nonce) and a signed session cookie with sub + tenant.
- middleware accepts the signed session as a verified principal; Bearer wins.
- dev login POST is refused in production.
- Sign-in link in the portal shell.
2026-11-02 15:48:02 +01:00

18 lines
599 B
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { verifySession, SESSION_COOKIE } from '@/lib/auth';
// GET /api/auth/me — current session (or null).
export async function GET(req: NextRequest) {
const token = req.cookies.get(SESSION_COOKIE)?.value;
const session = await verifySession(token);
return NextResponse.json({
user: session
? {
email: session.email ?? null,
sub: typeof session.sub === 'string' ? session.sub : null,
tenantId: typeof session.tenantId === 'string' ? session.tenantId : null,
}
: null,
});
}