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 },