47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
import * as express from "express";
|
|
import { createVerifier } from "fast-jwt";
|
|
|
|
import HttpError from "../interfaces/http-error";
|
|
import HttpStatusCode from "../interfaces/http-status";
|
|
|
|
if (!process.env.PUBLIC_KEY && !process.env.REALM_URL) {
|
|
throw new Error("Require public key or realm url.");
|
|
}
|
|
|
|
const jwtVerify = createVerifier({
|
|
key: async () => {
|
|
return `-----BEGIN PUBLIC KEY-----\n${process.env.PUBLIC_KEY}\n-----END PUBLIC KEY-----`;
|
|
},
|
|
});
|
|
|
|
export async function expressAuthentication(
|
|
request: express.Request,
|
|
securityName: string,
|
|
scopes?: string[],
|
|
) {
|
|
if (process.env.AUTH_BYPASS) return { preferred_username: "bypassed" };
|
|
|
|
if (securityName !== "bearerAuth") throw new Error("Unknown authentication method.");
|
|
|
|
const token = request.headers["authorization"]?.includes("Bearer ")
|
|
? request.headers["authorization"].split(" ")[1]
|
|
: null;
|
|
|
|
if (!token) throw new HttpError(HttpStatusCode.UNAUTHORIZED, "No token provided.");
|
|
|
|
const payload = await jwtVerify(token).catch((_) => null);
|
|
|
|
if (!payload) {
|
|
throw new HttpError(HttpStatusCode.UNAUTHORIZED, "Invalid token provided.");
|
|
}
|
|
|
|
if (
|
|
scopes &&
|
|
scopes.length > 0 &&
|
|
scopes.some((v) => !payload.resource_access[payload.azp].roles.includes(v))
|
|
) {
|
|
throw new HttpError(HttpStatusCode.FORBIDDEN, "You are not allowed to perform this action.");
|
|
}
|
|
|
|
return payload;
|
|
}
|