UNPKG

nestjs-appwrite

Version:

Easier Appwrite integration for your NestJS application.

69 lines (58 loc) 2.36 kB
import { CanActivate, ExecutionContext, Inject, Injectable, Logger, OnApplicationBootstrap, } from '@nestjs/common'; import * as jwt from 'jsonwebtoken'; import { Client } from 'node-appwrite'; import { AppwriteUnauthorizedException } from '../exceptions/appwrite-unauthorized.exception'; import { CONFIG_PROVIDER_NAME, INVALID_TOKEN } from '../appwrite.constants'; import { SecretStoreService } from '../service/secret-store.service'; import { SignTokenPayload } from '../domain/sign-token-payload'; import { ClientWithToken } from '../domain/client-with-token'; import { Config } from '../config/config.interface'; const JWT_SECRET = 'jwt_secret'; const BEARER_PREFIX = 'Bearer '; @Injectable() export class AccessTokenGuard implements CanActivate, OnApplicationBootstrap { private readonly logger = new Logger(AccessTokenGuard.name); private jwtSecret: string | undefined; constructor( private readonly storeService: SecretStoreService, @Inject(CONFIG_PROVIDER_NAME) private readonly config: Config, ) { } public async onApplicationBootstrap(): Promise<void> { this.jwtSecret = await this.storeService.getSecretString(JWT_SECRET); } public async canActivate(context: ExecutionContext): Promise<boolean> { if (!this.jwtSecret) { this.logger.error(`Secret ${JWT_SECRET} is undefined, unable to verify tokens`); throw new AppwriteUnauthorizedException(INVALID_TOKEN, 'Unable to validate the token'); } const req = context.switchToHttp().getRequest(); const { authorization } = req.headers; if (!authorization) { throw new AppwriteUnauthorizedException(INVALID_TOKEN, 'Missing authorization header'); } const formattedToken = authorization?.replace(BEARER_PREFIX, '') ?? ''; try { const decodedToken = jwt.verify(formattedToken, this.jwtSecret) as SignTokenPayload; const client = new Client() .setEndpoint(this.config.APPWRITE_ENDPOINT) .setProject(this.config.APPWRITE_PROJECT_ID) .setJWT(formattedToken); (client as ClientWithToken).decodedToken = decodedToken; if (!req.body) { req.body = {}; } req.body.client = client; return true; } catch (err) { this.logger.error(err); throw new AppwriteUnauthorizedException(INVALID_TOKEN, 'Invalid authorization token'); } } }