generated from bastian/boilerplate
72 lines
2.1 KiB
TypeScript
72 lines
2.1 KiB
TypeScript
import { Controller, Get, Query, Redirect, Req, Res } from '@nestjs/common';
|
|
import type { Response } from 'express';
|
|
import type { AuthenticatedRequest } from './authenticated-request';
|
|
import { Public } from './guards/public.decorator';
|
|
import { AppConfigService } from '../config/config.service';
|
|
import { SensitiveRateLimit } from '../common/rate-limit/sensitive-rate-limit.decorator';
|
|
import { AuthService } from './auth.service';
|
|
|
|
@Controller('auth')
|
|
export class AuthController {
|
|
constructor(
|
|
private readonly auth: AuthService,
|
|
private readonly config: AppConfigService,
|
|
) {}
|
|
|
|
@Get('login')
|
|
@Public()
|
|
@SensitiveRateLimit()
|
|
@Redirect()
|
|
async login(@Query('returnTo') returnTo?: string) {
|
|
return { url: await this.auth.createLoginUrl(returnTo) };
|
|
}
|
|
|
|
@Get('callback')
|
|
@Public()
|
|
@SensitiveRateLimit()
|
|
async callback(
|
|
@Query('code') code: string,
|
|
@Query('state') state: string,
|
|
@Req() req: AuthenticatedRequest,
|
|
@Res() res: Response,
|
|
) {
|
|
const { session, csrfToken, returnPath } = await this.auth.completeLogin(
|
|
code,
|
|
state,
|
|
req.get('user-agent'),
|
|
req.ip,
|
|
);
|
|
res.cookie(this.config.session.cookieName, session.id, {
|
|
httpOnly: true,
|
|
signed: true,
|
|
secure: this.config.isProduction,
|
|
sameSite: 'lax',
|
|
path: '/',
|
|
expires: session.absoluteExpiresAt,
|
|
});
|
|
res.cookie('csrf_token', csrfToken, {
|
|
httpOnly: false,
|
|
secure: this.config.isProduction,
|
|
sameSite: 'lax',
|
|
path: '/',
|
|
expires: session.absoluteExpiresAt,
|
|
});
|
|
res.redirect(
|
|
new URL(returnPath ?? '/', this.config.frontendBaseUrl).toString(),
|
|
);
|
|
}
|
|
|
|
@Get('logout')
|
|
@Public()
|
|
@SensitiveRateLimit()
|
|
async logout(@Req() req: AuthenticatedRequest, @Res() res: Response) {
|
|
const sessionId = req.signedCookies?.[this.config.session.cookieName] as
|
|
| string
|
|
| undefined;
|
|
const logoutUrl = await this.auth.logout(sessionId);
|
|
res.clearCookie(this.config.session.cookieName, { path: '/' });
|
|
res.clearCookie('csrf_token', { path: '/' });
|
|
res.redirect(logoutUrl);
|
|
}
|
|
}
|