nestjs-appwrite
Version:
Easier Appwrite integration for your NestJS application.
69 lines (58 loc) • 2.36 kB
text/typescript
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 ';
()
export class AccessTokenGuard implements CanActivate, OnApplicationBootstrap {
private readonly logger = new Logger(AccessTokenGuard.name);
private jwtSecret: string | undefined;
constructor(
private readonly storeService: SecretStoreService,
(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');
}
}
}