49 lines
1.4 KiB
TypeScript
49 lines
1.4 KiB
TypeScript
export const getRawJsonWebToken = (): string | null => {
|
|
return localStorage.getItem('token');
|
|
}
|
|
|
|
export const getJsonWebToken = (): JwtPayload | null => {
|
|
const rawToken = getRawJsonWebToken();
|
|
return rawToken ? parseJwt(rawToken) : null
|
|
}
|
|
|
|
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 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';
|
|
}
|
|
|
|
const claims = ["role", "person_row_id", "exp", "iat", "aud", "iss"]
|
|
const userRoles = ["candymat_editor", 'candymat_candidate', 'candymat_person']
|
|
|
|
interface JwtPayload {
|
|
"role": UserRole,
|
|
"person_row_id": number,
|
|
"exp": number,
|
|
"iat": number,
|
|
"aud": "postgraphile",
|
|
"iss": "postgraphile"
|
|
}
|
|
|
|
type UserRole = "candymat_editor" | 'candymat_candidate' | 'candymat_person'
|
|
|