feat: verify online and management role
This commit is contained in:
parent
d6bf3ed879
commit
a7f012bda2
10 changed files with 117 additions and 62 deletions
|
|
@ -1,12 +1,19 @@
|
|||
import * as express from "express";
|
||||
import { createVerifier } from "fast-jwt";
|
||||
import { createDecoder, createVerifier } from "fast-jwt";
|
||||
|
||||
import HttpError from "../interfaces/http-error";
|
||||
import HttpStatusCode from "../interfaces/http-status";
|
||||
import { JwtPayload } from "jsonwebtoken";
|
||||
|
||||
if (!process.env.PUBLIC_KEY && !process.env.REALM_URL) {
|
||||
if (!(process.env.PUBLIC_KEY && process.env.REALM_URL)) {
|
||||
throw new Error("Require public key or realm url.");
|
||||
}
|
||||
if (process.env.PUBLIC_KEY && process.env.REALM_URL && !process.env.PREFERRED_AUTH) {
|
||||
throw new Error("Preferred auth type must be specified if public key and realm url is provided.");
|
||||
}
|
||||
if (!process.env.MANAGEMENT_ROLE) {
|
||||
throw new Error("Management role env is required.");
|
||||
}
|
||||
|
||||
const jwtVerify = createVerifier({
|
||||
key: async () => {
|
||||
|
|
@ -14,6 +21,8 @@ const jwtVerify = createVerifier({
|
|||
},
|
||||
});
|
||||
|
||||
const jwtDecode = createDecoder();
|
||||
|
||||
export async function expressAuthentication(
|
||||
request: express.Request,
|
||||
securityName: string,
|
||||
|
|
@ -29,19 +38,47 @@ export async function expressAuthentication(
|
|||
|
||||
if (!token) throw new HttpError(HttpStatusCode.UNAUTHORIZED, "No token provided.");
|
||||
|
||||
const payload = await jwtVerify(token).catch((_) => null);
|
||||
let payload: JwtPayload = {};
|
||||
|
||||
if (!payload) {
|
||||
throw new HttpError(HttpStatusCode.UNAUTHORIZED, "Invalid token provided.");
|
||||
switch (process.env.PREFERRED_AUTH) {
|
||||
case "online":
|
||||
payload = await verifyOnline(token);
|
||||
break;
|
||||
case "offline":
|
||||
payload = await verifyOffline(token);
|
||||
break;
|
||||
default:
|
||||
if (process.env.REALM_URL) payload = await verifyOnline(token);
|
||||
if (process.env.PUBLIC_KEY) payload = await verifyOffline(token);
|
||||
break;
|
||||
}
|
||||
|
||||
if (
|
||||
scopes &&
|
||||
scopes.length > 0 &&
|
||||
scopes.some((v) => !payload.resource_access[payload.azp].roles.includes(v))
|
||||
scopes
|
||||
.map((v) => (v === "management-role" ? process.env.MANAGEMENT_ROLE : v))
|
||||
.every((v) => !payload.resource_access[payload.azp].roles.includes(v))
|
||||
) {
|
||||
throw new HttpError(HttpStatusCode.FORBIDDEN, "You are not allowed to perform this action.");
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
async function verifyOffline(token: string) {
|
||||
const payload = await jwtVerify(token).catch((_) => null);
|
||||
if (!payload) throw new HttpError(HttpStatusCode.UNAUTHORIZED, "Invalid token provided.");
|
||||
return payload;
|
||||
}
|
||||
|
||||
async function verifyOnline(token: string) {
|
||||
const res = await fetch(`${process.env.REALM_URL}/protocol/openid-connect/userinfo`, {
|
||||
headers: { authorization: `Bearer ${token}` },
|
||||
}).catch((e) => console.error(e));
|
||||
|
||||
if (!res) throw new Error("Cannot connect to auth service.");
|
||||
if (!res.ok) throw new HttpError(HttpStatusCode.UNAUTHORIZED, "Invalid token provided.");
|
||||
|
||||
return await jwtDecode(token);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue