kandimat/redaktions-app/src/jwt/jwt.ts
2021-04-21 20:25:44 +02:00

73 lines
1.9 KiB
TypeScript

import { client } from "../backend/helper";
type Claim = "role" | "person_row_id" | "exp" | "iat" | "aud" | "iss";
export type UserRole =
| "candymat_editor"
| "candymat_candidate"
| "candymat_person";
export interface JwtPayload {
role: UserRole;
person_row_id: number;
exp: number;
iat: number;
aud: "postgraphile";
iss: "postgraphile";
}
const CLAIMS: Claim[] = ["role", "person_row_id", "exp", "iat", "aud", "iss"];
const USER_ROLES: UserRole[] = [
"candymat_editor",
"candymat_candidate",
"candymat_person",
];
export const getRawJsonWebToken = (): string | null => {
return localStorage.getItem("token");
};
export const isJwtPayloadValid = (jwtPayload: unknown): boolean => {
const jwt = Object(jwtPayload);
return (
CLAIMS.every((claim) => Object.keys(jwt).includes(claim)) &&
USER_ROLES.includes(jwt.role) &&
typeof jwt.person_row_id === "number" &&
typeof jwt.exp === "number" &&
typeof jwt.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;
};
export const logoutUser = async (): Promise<void> => {
try {
await client.cache.reset();
} catch (e) {
console.error(e);
}
localStorage.removeItem("token");
window.location.reload();
};
export const isLoggedIn = (): boolean => !!getJsonWebToken();