79 lines
2.2 KiB
TypeScript

import { NextFunction, Request, Response } from "express"
import path from "path"
import { constants, promises as fs } from "fs"
import { verify, sign } from "jsonwebtoken"
import config from "../config"
type AuthorizedRequest = Request & { headers: { authorization: string } }
let cachedSecret: string
const SECRET_PATH = path.resolve(process.cwd(), "access/jwt_secret.json")
getSecret() // Necessary until we can make async express middleware
export function secure(request: AuthorizedRequest, response: Response, next: NextFunction): void {
if (!cachedSecret) {
response.status(408).json({
error: "Server still loading",
})
return
}
const rawToken = request.headers.authorization
const token1 = rawToken && rawToken.split(/\s/)[1]
const token2 = request.cookies?.jwt
const token = token1 || token2
verify(token, cachedSecret, (tokenError: any, decoded: any) => {
if (tokenError) {
response.status(200).json({
error: "Accès interdit sans identification",
})
return
}
response.locals.jwt = decoded
next()
})
}
let hasSecretReturn: boolean | undefined
export async function hasSecret(): Promise<boolean> {
if (hasSecretReturn !== undefined) {
return hasSecretReturn
}
try {
// eslint-disable-next-line no-bitwise
await fs.access(SECRET_PATH, constants.R_OK | constants.W_OK)
hasSecretReturn = true
} catch {
hasSecretReturn = false
}
return hasSecretReturn
}
async function getSecret() {
if (!cachedSecret) {
try {
const secretContent = await fs.readFile(SECRET_PATH)
cachedSecret = secretContent && JSON.parse(secretContent.toString()).secret
} catch (e: any) {
cachedSecret = config.DEV_JWT_SECRET
}
}
return cachedSecret
}
export async function getJwt(id: number, roles: string[]): Promise<string> {
const jwt = sign(
{ id, roles },
await getSecret()
// __TEST__
// ? undefined
// : {
// expiresIn: "365d",
// }
)
return jwt
}