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<User|undefined> {
|
|
// 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 = <ITokenSchema>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<T extends IAuthMiddlewareParams>(request: MiddlewareRequest<T>, reply: FastifyReply, next: IteratorNext) {
|
|
let user = await authenticateJwtToken(request, reply);
|
|
if (user === undefined) {
|
|
// The authenticateJwtToken function sends out the response
|
|
return;
|
|
}
|
|
request.middlewareParams = <any><IAuthMiddlewareParams>{
|
|
auth: { user }
|
|
};
|
|
next();
|
|
}
|