/** * OIDC Login Controller * * Provides a simple login page for OIDC authorization flows. * When users access the authorization endpoint without being logged in, * Better Auth redirects them here. After successful login, users are * redirected back to continue the authorization flow. */ import { Controller, Get, Post, Req, Res, Body, Query } from '@nestjs/common'; import { Request, Response } from 'express'; import { BetterAuthService } from './services/better-auth.service'; @Controller() export class OidcLoginController { constructor(private readonly betterAuthService: BetterAuthService) {} /** * GET /login - Display login page * * Shows a simple login form. OIDC parameters are preserved in the URL * so they can be passed back to the authorization endpoint after login. */ @Get('login') async getLoginPage(@Query() query: Record, @Res() res: Response) { // Handle returnUrl parameter (when redirected from authorization endpoint) let returnUrl = query.returnUrl || '/'; let clientId: string | undefined = query.client_id; // If no direct client_id but we have returnUrl, extract client_id from it if (!clientId && query.returnUrl) { try { const returnUrlParams = new URLSearchParams(query.returnUrl.split('?')[1] || ''); clientId = returnUrlParams.get('client_id') ?? undefined; } catch { // Ignore parsing errors } } // If no returnUrl was provided, build one from query params (direct OIDC flow) if (!query.returnUrl && Object.keys(query).length > 0) { const queryString = new URLSearchParams(query).toString(); returnUrl = `/api/auth/oauth2/authorize?${queryString}`; } // Get client name for display const clientName = this.getClientDisplayName(clientId || 'Unknown'); const html = ` Sign In - Mana Core

Signing in to ${clientName}

`; res.setHeader('Content-Type', 'text/html'); return res.send(html); } /** * Get display name for OIDC client */ private getClientDisplayName(clientId: string): string { const clientNames: Record = { 'matrix-synapse': 'Matrix Chat', }; return clientNames[clientId] || clientId; } }