import { FastifyReply, FastifyRequest } from "fastify"; import Application from "@server/Application"; import jwt from "jsonwebtoken"; import { IteratorNext, MiddlewareRequest } from "."; import { ITokenSchema } from "@common/api_schema"; import { User } from "@server/database/entities"; /** * Attempt to authenticate a client's JWT token */ async function authenticateJwtToken(request: FastifyRequest, reply: FastifyReply): Promise { // Verify headers if (!request.headers["authorization"]) { reply.status(401); reply.send({ status: "Unauthorized" }); return; } if (!request.headers["authorization"].startsWith("Bearer ")) { reply.status(400); reply.send({ status: "Bad request" }); return; } // Construct the token string let token = request.headers["authorization"].slice(7).trim(); if ((token.match(/\./g)||[]).length < 2) { token += '.' + (request.cookies.jwt_signature ?? "").trim(); } // Decode the token let user: User; try { let decoded = jwt.verify(token, Application.instance().APP_KEY); user = await User.findOneOrFail(decoded.id); } catch(e) { reply.status(401); reply.send({ status: "Unauthorized" }); return; } return user; } /** * The parameter types for the auth middleware */ export interface IAuthMiddlewareParams { auth: { user: User } } /** * Ensure that a valid authentication token is provided */ export async function auth(request: MiddlewareRequest, reply: FastifyReply, next: IteratorNext) { let user = await authenticateJwtToken(request, reply); if (user === undefined) { // The authenticateJwtToken function sends out the response return; } request.middlewareParams = { auth: { user } }; next(); }