kandimat/redaktions-app/src/jwt/jwt.ts
Christoph Lienhard b26d6d6e69
Fix "used before it was defined" warning
* updated react-scripts (fix eslint-plugin problems)
* reorder functions where needed
2021-02-07 23:06:58 +01:00

50 lines
1.4 KiB
TypeScript

type UserRole = "candymat_editor" | "candymat_candidate" | "candymat_person";
interface JwtPayload {
role: UserRole;
person_row_id: number;
exp: number;
iat: number;
aud: "postgraphile";
iss: "postgraphile";
}
const claims = ["role", "person_row_id", "exp", "iat", "aud", "iss"];
const userRoles = ["candymat_editor", "candymat_candidate", "candymat_person"];
export const getRawJsonWebToken = (): string | null => {
return localStorage.getItem("token");
};
export const isJwtPayloadValid = (jwtPayload: JwtPayload): boolean => {
return (
claims.every((claim) => Object.keys(jwtPayload).includes(claim)) &&
userRoles.includes(jwtPayload.role) &&
typeof jwtPayload.person_row_id === "number" &&
typeof jwtPayload.exp === "number" &&
typeof jwtPayload.iat === "number"
);
};
export const parseJwt = (token: string): JwtPayload | null => {
try {
const base64Url = token.split(".")[1];
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
const jsonPayload = decodeURIComponent(
atob(base64)
.split("")
.map((c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2))
.join("")
);
const jwtPayload = JSON.parse(jsonPayload);
return isJwtPayloadValid(jwtPayload) ? jwtPayload : null;
} catch {
return null;
}
};
export const getJsonWebToken = (): JwtPayload | null => {
const rawToken = getRawJsonWebToken();
return rawToken ? parseJwt(rawToken) : null;
};