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 1859x 1859x 1859x 43x 3558x 3558x 3502x 3502x 3502x 1147x 1147x 43x 502x 502x 502x 8x 500x 43x 5417x 1844x 2945x 628x 43x 1926x 581x 1719x 581x 603x 1901x | 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);
};
|