import { Body, Controller, Get, Param, Post, Req, Res, UnauthorizedException } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { Request, Response } from 'express'; import type { Interaction } from 'oidc-provider'; import { OidcProviderService } from './oidc-provider.service'; @Controller('interaction') export class OidcInteractionController { constructor( private readonly oidc: OidcProviderService, private readonly config: ConfigService, ) {} @Get(':uid') async view(@Param('uid') uid: string, @Req() request: Request, @Res() response: Response) { const details = await this.oidc.interactionDetails(request, response); if (details.uid !== uid) { response.status(400).send(this.page('Ungueltige Anfrage', '
Die OIDC-Interaktion ist ungueltig.
')); return; } if (details.prompt.name === 'login') { response.send(this.page('Anmelden', this.loginForm(uid))); return; } if (details.prompt.name === 'consent') { const clientId = String(details.params.client_id ?? ''); if (clientId && (await this.oidc.isFirstPartyClient(clientId))) { await this.oidc.finishConsent(request, response, uid, { autoGranted: true }); return; } response.send(this.page('Zugriff erlauben', this.consentView(uid, details))); return; } response.status(400).send(this.page('OIDC', 'Diese Interaktion wird noch nicht unterstuetzt.
')); } @Post(':uid/login') async login( @Param('uid') uid: string, @Body() body: { username?: string; password?: string }, @Req() request: Request, @Res() response: Response, ) { const username = body.username ?? ''; try { await this.oidc.finishLogin(request, response, uid, username, body.password ?? ''); } catch (error) { if (this.isInvalidCredentialsError(error)) { response .status(401) .send(this.page('Anmelden', this.loginForm(uid, username, 'Ungueltige Zugangsdaten.'))); return; } throw error; } } @Post(':uid/confirm') async confirm(@Param('uid') uid: string, @Req() request: Request, @Res() response: Response) { await this.oidc.finishConsent(request, response, uid); } @Post(':uid/abort') async abort(@Req() request: Request, @Res() response: Response) { await this.oidc.abortInteraction(request, response); } private loginForm(uid: string, username = '', errorMessage = ''): string { const encodedUid = encodeURIComponent(uid); const error = errorMessage ? `` : ''; return ` ${error} `; } private consentView(uid: string, details: Interaction): string { const encodedUid = encodeURIComponent(uid); const clientId = String(details.params.client_id ?? ''); const clientName = String(details.params.name ?? (clientId || 'Unbekannte Anwendung')); const redirectUri = String(details.params.redirect_uri ?? ''); const scope = String(details.params.scope ?? 'openid'); return `Die Anwendung ${this.escape(clientName)} moechte auf dein Konto zugreifen.
${redirectUri ? `` : ''}