import { AccountService } from './account/account.service'; import { AppService } from './app.service'; import { env } from './config/env'; import { AuthParams, Params } from './decorators/auth-mode.decorator'; import { AuthToken } from './decorators/token.decorator'; import { LdapService } from './ldap/ldap.service'; import { isTokenExpired } from './utils/error'; import { Controller, Get, HttpStatus, Req, Res } from '@nestjs/common'; import { ApiExcludeController } from '@nestjs/swagger'; import { FastifyReply, FastifyRequest } from 'fastify'; import { cookieOptions } from 'src/config/cookie'; @Controller() @ApiExcludeController() export class AppController { constructor( private readonly appService: AppService, private readonly accountService: AccountService, private readonly ldapService: LdapService ) {} @Get('auth') public async auth( @Req() req: FastifyRequest, @Res() reply: FastifyReply, @AuthToken() token: string, @AuthParams() authParams: Params ) { try { return this.handleDefaultCheck(req, reply, token); } catch (error) { if (isTokenExpired(error)) { try { return this.handleExpiredToken(authParams, token, req, reply); } catch { return this.handleError(req, reply); } } return this.handleError(req, reply); } } private async handleExpiredToken( { authMode, refreshToken }: Params, token: string, req: FastifyRequest, reply: FastifyReply ) { if (!refreshToken) return this.handleError(req, reply); try { let newToken = ''; if (authMode === 'ldap-tfa') { const { aud } = this.appService.checkToken(token); if (aud === 'auth') return this.handleError(req, reply); newToken = await this.ldapService.refreshToken(token); } if (authMode === 'ldap') { newToken = await this.ldapService.refreshToken(token); } if (authMode === 'account') { newToken = await this.accountService.refreshToken(token); } reply.header('Authorization', `Bearer ${newToken}`); return reply.setCookie(env.COOKIE_TOKEN_NAME, newToken, cookieOptions).send(); } catch { return this.handleError(req, reply); } } private handleDefaultCheck(req: FastifyRequest, reply: FastifyReply, token: string) { this.appService.checkToken(token); const { aud } = this.appService.checkToken(token); if (aud === 'auth') return this.handleError(req, reply); reply.header('Authorization', `Bearer ${token}`); return reply.send(); } private handleError(_req: FastifyRequest, reply: FastifyReply) { return reply.status(HttpStatus.UNAUTHORIZED).send(); } }