From 29c5d2b29a5477ef815d64f70ce6f687ef4c46e2 Mon Sep 17 00:00:00 2001 From: Till-JS <101404291+Till-JS@users.noreply.github.com> Date: Thu, 29 Jan 2026 12:55:02 +0100 Subject: [PATCH] feat(auth): add OIDC login page for Matrix SSO Add a simple login page at /login for OIDC authorization flows. When users access the authorization endpoint without being logged in, Better Auth redirects them to this page. After successful login, users are redirected back to continue the authorization flow. - Create OidcLoginController with login page HTML - Add controller to AuthModule - Exclude /login from global prefix Co-Authored-By: Claude Opus 4.5 --- .../mana-core-auth/src/auth/auth.module.ts | 3 +- .../src/auth/oidc-login.controller.ts | 253 ++++++++++++++++++ services/mana-core-auth/src/main.ts | 2 + 3 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 services/mana-core-auth/src/auth/oidc-login.controller.ts diff --git a/services/mana-core-auth/src/auth/auth.module.ts b/services/mana-core-auth/src/auth/auth.module.ts index 47298364a..961c6331a 100644 --- a/services/mana-core-auth/src/auth/auth.module.ts +++ b/services/mana-core-auth/src/auth/auth.module.ts @@ -2,12 +2,13 @@ import { Module, forwardRef } from '@nestjs/common'; import { AuthController } from './auth.controller'; import { BetterAuthPassthroughController } from './better-auth-passthrough.controller'; import { OidcController } from './oidc.controller'; +import { OidcLoginController } from './oidc-login.controller'; import { BetterAuthService } from './services/better-auth.service'; import { ReferralsModule } from '../referrals/referrals.module'; @Module({ imports: [forwardRef(() => ReferralsModule)], - controllers: [AuthController, BetterAuthPassthroughController, OidcController], + controllers: [AuthController, BetterAuthPassthroughController, OidcController, OidcLoginController], providers: [BetterAuthService], exports: [BetterAuthService], }) diff --git a/services/mana-core-auth/src/auth/oidc-login.controller.ts b/services/mana-core-auth/src/auth/oidc-login.controller.ts new file mode 100644 index 000000000..b77bfefee --- /dev/null +++ b/services/mana-core-auth/src/auth/oidc-login.controller.ts @@ -0,0 +1,253 @@ +/** + * 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) { + const queryString = new URLSearchParams(query).toString(); + const returnUrl = queryString ? `/api/auth/oauth2/authorize?${queryString}` : '/'; + + // Get client name for display + const clientId = query.client_id || 'Unknown'; + const clientName = this.getClientDisplayName(clientId); + + 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; + } +} diff --git a/services/mana-core-auth/src/main.ts b/services/mana-core-auth/src/main.ts index 933909241..b95692464 100644 --- a/services/mana-core-auth/src/main.ts +++ b/services/mana-core-auth/src/main.ts @@ -86,6 +86,8 @@ async function bootstrap() { exclude: [ { path: 'metrics', method: RequestMethod.ALL }, { path: 'health', method: RequestMethod.ALL }, + // OIDC login page + { path: 'login', method: RequestMethod.ALL }, // Better Auth routes (verification emails, password reset) { path: 'api/auth/verify-email', method: RequestMethod.ALL }, { path: 'api/auth/reset-password/(.*)', method: RequestMethod.ALL },