Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | 43x 43x 1440x 1440x 1440x 43x 3009x 3009x 2953x 2953x 2953x 977x 977x 43x 421x 421x 421x 8x 419x 43x 4449x 1425x 2481x 543x 43x 1628x 496x 1464x 496x 518x 1603x | import jsonwebtoken from "jsonwebtoken";
import { config } from "shared/config";
import { UserGroup } from "shared/types/models/user";
import { exhaustiveSwitchGuard } from "shared/utils/exhaustiveSwitchGuard";
import { JWTBody, JWTBodySchema, JWTResponse } from "server/types/jwtTypes";
import { logger } from "server/utils/logger";
const { TokenExpiredError } = jsonwebtoken;
type SignOptions = jsonwebtoken.SignOptions;
export const getJWT = (userGroup: UserGroup, username: string): string => {
const payload = {
username,
userGroup,
};
const options: SignOptions = {
expiresIn: "14 days",
};
return jsonwebtoken.sign(payload, getSecret(userGroup), options);
};
export const verifyJWT = (jwt: string, userGroup: UserGroup): JWTResponse => {
try {
const jwtBody = jsonwebtoken.verify(jwt, getSecret(userGroup));
const result = JWTBodySchema.safeParse(jwtBody);
Iif (!result.success) {
// A valid signature with an invalid body means we created a bad JWT -
// log it, unlike tampered tokens which are just noise
logger.error(
new Error("Error validating JWT body", { cause: result.error }),
);
return {
status: "error",
message: "Unknown JWT error",
body: { username: "", userGroup: UserGroup.USER, iat: 0, exp: 0 },
};
}
return {
body: {
username: result.data.username,
userGroup: result.data.userGroup,
iat: result.data.iat,
exp: result.data.exp,
},
status: "success",
message: "success",
};
} catch (error) {
Iif (error instanceof TokenExpiredError) {
return {
status: "error",
message: "Expired JWT",
body: { username: "", userGroup: UserGroup.USER, iat: 0, exp: 0 },
};
}
return {
status: "error",
message: "Unknown JWT error",
body: { username: "", userGroup: UserGroup.USER, iat: 0, exp: 0 },
};
}
};
// Be careful: this does not verify JWT signature
export const decodeJWT = (jwt: string): JWTBody | null => {
const decodedJwt = jsonwebtoken.decode(jwt);
const result = JWTBodySchema.safeParse(decodedJwt);
if (!result.success) {
return null;
}
return result.data;
};
const getSecret = (userGroup: UserGroup): string => {
switch (userGroup) {
case UserGroup.ADMIN: {
return config.server().jwtSecretKeyAdmin;
}
case UserGroup.USER: {
return config.server().jwtSecretKey;
}
case UserGroup.HELPER: {
return config.server().jwtSecretKeyHelp;
}
default:
return exhaustiveSwitchGuard(userGroup);
}
};
export const getJwtResponse = (
jwt: string,
requiredUserGroup: UserGroup | UserGroup[],
): JWTResponse => {
if (Array.isArray(requiredUserGroup)) {
const responses = requiredUserGroup.map((userGroup) => {
return verifyJWT(jwt, userGroup);
});
return (
responses.find((response) => response.status === "success") ??
responses[0]
);
}
return verifyJWT(jwt, requiredUserGroup);
};
|