diff --git a/src/services/auth/auth-lib.ts b/src/services/auth/auth-lib.ts index 89aa6d4b..ae1fc150 100644 --- a/src/services/auth/auth-lib.ts +++ b/src/services/auth/auth-lib.ts @@ -51,8 +51,8 @@ export async function getJwtPayloadFromProfile(provider: string, data: ProfileDa if (userRoles.length) { payload.roles = userRoles; } - }).catch((error: Error) => { - console.log("get function failed!"); + }).catch((error: string) => { + console.log("get function failed inside getRoles!"); console.log(error); }); @@ -60,8 +60,8 @@ export async function getJwtPayloadFromProfile(provider: string, data: ProfileDa if (!payload.roles.length) { await initializeRoles(userId, provider as Provider, email).then((newRoles: Role[]) => { payload.roles = newRoles; - }).catch((error: Error) => { - console.log("get function failed!"); + }).catch((error: string) => { + console.log("get function failed inside initializeRoles!"); console.log(error); }); } @@ -117,7 +117,8 @@ export function generateJwtToken(payload?: JwtPayload, expiration?: string): str // // Appends an expiry field to the JWT token const options: SignOptions = { }; - payload.exp = ms(expiration ?? "7d"); + payload.exp = Math.floor(Date.now() + ms(expiration ?? "7d")) / Constants.MILLISECONDS_PER_SECOND; + console.log(payload.exp); // Generate a token, and return it const token: string = jsonwebtoken.sign(payload, secret, options); @@ -175,6 +176,7 @@ export async function getAuthInfo(id: string): Promise { // Null check to ensure that we're not returning anything null if (!info) { + console.log("rejecting..."); return Promise.reject("User ID does not exist in the database!"); } @@ -186,14 +188,15 @@ export async function getAuthInfo(id: string): Promise { export async function getRoles(id: string): Promise { + let roles: Role[] | undefined; // Call helper function to get auth info, and just return data from there - getAuthInfo(id).then((info: RolesSchema) => { - return info.roles as Role[]; + await getAuthInfo(id).then((user: RolesSchema) => { + roles = user.roles as Role[]; }).catch((error: string) => { return Promise.reject(error); }); - return Promise.reject("Unknown error!"); + return roles ?? Promise.reject("Unknown error!"); } diff --git a/src/services/auth/auth-router.ts b/src/services/auth/auth-router.ts index 92ed9106..a526c534 100644 --- a/src/services/auth/auth-router.ts +++ b/src/services/auth/auth-router.ts @@ -7,10 +7,12 @@ import { Profile as GoogleProfile, Strategy as GoogleStrategy } from "passport-g import { Role } from "../../models.js"; import Constants from "../../constants.js"; +import { verifyJwt } from "../../middleware/verify-jwt.js"; import { SelectAuthProvider } from "../../middleware/select-auth.js"; + +import { ModifyRoleRequest } from "./auth-formats.js"; import { JwtPayload, ProfileData, Provider, RoleOperation } from "./auth-models.js"; import { decodeJwtToken, generateJwtToken, getJwtPayloadFromProfile, getRoles, hasElevatedPerms, updateRoles, verifyFunction } from "./auth-lib.js"; -import { ModifyRoleRequest } from "./auth-formats.js"; passport.use(Provider.GITHUB, new GitHubStrategy({ @@ -71,7 +73,7 @@ authRouter.get("/:PROVIDER/callback/", (req: Request, res: Response, next: NextF }); -authRouter.get("/roles/:USERID", async (req: Request, res: Response) => { +authRouter.get("/roles/:USERID", verifyJwt, async (req: Request, res: Response) => { const targetUser: string | undefined = req.params.USERID; // Check if we have a user to get roles for - if not, get roles for current user @@ -80,31 +82,34 @@ authRouter.get("/roles/:USERID", async (req: Request, res: Response) => { return; } - try { - const payload: JwtPayload = decodeJwtToken(req.headers.authorization); - - // Cases: Target user already logged in, auth user is admin - if (payload.id == targetUser) { - res.status(Constants.SUCCESS).send({id: payload.id, roles: payload.roles}); - } else if (hasElevatedPerms(payload)) { - let roles: Role[] = []; - await getRoles(targetUser).then((targetRoles: Role[]) => { - roles = targetRoles; - }).catch((error: Error) => { - throw error; - }); - console.log(roles); + const payload: JwtPayload = res.locals.payload as JwtPayload; + + // Cases: Target user already logged in, auth user is admin + if (payload.id == targetUser) { + res.status(Constants.SUCCESS).send({id: payload.id, roles: payload.roles}); + } else if (hasElevatedPerms(payload)) { + let roles: Role[] = []; + await getRoles(targetUser).then((targetRoles: Role[]) => { + roles = targetRoles; res.status(Constants.SUCCESS).send({id: targetUser, roles: roles}); - } else { - res.status(Constants.FORBIDDEN).send("not authorized to perform this operation!"); - } - } catch (error) { - res.status(Constants.FORBIDDEN).send(error); + }).catch((error: Error) => { + console.log(error); + res.status(Constants.INTERNAL_ERROR).send(error); + }); + } else { + res.status(Constants.FORBIDDEN).send("not authorized to perform this operation!"); } }); -authRouter.put("/roles/:OPERATION/", async (req: Request, res: Response) => { +authRouter.put("/roles/:OPERATION/", verifyJwt, async (req: Request, res: Response) => { + const payload: JwtPayload = res.locals.payload as JwtPayload; + + // Not authenticated with modify roles perms + if (!hasElevatedPerms(payload)) { + res.status(Constants.FORBIDDEN).send({error: "not permitted to modify roles!"}); + } + // Parse to get operation type const op: RoleOperation | undefined = RoleOperation[req.params.operation as keyof typeof RoleOperation]; @@ -114,95 +119,71 @@ authRouter.put("/roles/:OPERATION/", async (req: Request, res: Response) => { return; } - try { - const payload: JwtPayload = decodeJwtToken(req.headers.authorization); - - // Not authenticated with modify roles perms - if (!hasElevatedPerms(payload)) { - res.status(Constants.FORBIDDEN).send({error: "not permitted to modify roles!"}); - } - - // Check if role to add/remove actually exists - const data: ModifyRoleRequest = req.body as ModifyRoleRequest; - const role: Role | undefined = Role[data.role as keyof typeof Role]; - if (!role) { - res.status(Constants.BAD_REQUEST).send({error: "invalid role passed in!"}); - return; - } + // Check if role to add/remove actually exists + const data: ModifyRoleRequest = req.body as ModifyRoleRequest; + const role: Role | undefined = Role[data.role as keyof typeof Role]; + if (!role) { + res.status(Constants.BAD_REQUEST).send({error: "invalid role passed in!"}); + return; + } - // Try to update roles, if possible - await updateRoles(data.id, role, op).catch((error: string) => { - console.log(error); - res.status(Constants.INTERNAL_ERROR).send({error: error}); - }); + // Try to update roles, if possible + await updateRoles(data.id, role, op).catch((error: string) => { + console.log(error); + res.status(Constants.INTERNAL_ERROR).send({error: error}); + }); - // Get new roles for the current user, and return them - await getRoles(data.id).then((roles: Role[]) => { - res.status(Constants.SUCCESS).send({id: data.id, roles: roles}); - }).catch((error: string) => { - console.log(error); - res.status(Constants.INTERNAL_ERROR).send({error: error}); - }); - } catch (error) { - res.status(Constants.FORBIDDEN).send(error); - } + // Get new roles for the current user, and return them + await getRoles(data.id).then((roles: Role[]) => { + res.status(Constants.SUCCESS).send({id: data.id, roles: roles}); + }).catch((error: string) => { + console.log(error); + res.status(Constants.INTERNAL_ERROR).send({error: error}); + }); }); -authRouter.get("/list/roles/", (req: Request, res: Response) => { - try { - const payload: JwtPayload = decodeJwtToken(req.headers.authorization); +authRouter.get("/list/roles/", verifyJwt, (_: Request, res: Response) => { + const payload: JwtPayload = res.locals.payload as JwtPayload; - // Check if current user should be able to access all roles - if (!hasElevatedPerms(payload)) { - res.status(Constants.FORBIDDEN).send({error: "not authorized to perform this operation!"}); - return; - } + // Check if current user should be able to access all roles + if (!hasElevatedPerms(payload)) { + res.status(Constants.FORBIDDEN).send({error: "not authorized to perform this operation!"}); + return; + } - // Filter enum to get all possible string keys - const roles: string[] = Object.keys(Role).filter((item: string) => { - return isNaN(Number(item)); - }); + // Filter enum to get all possible string keys + const roles: string[] = Object.keys(Role).filter((item: string) => { + return isNaN(Number(item)); + }); - res.status(Constants.SUCCESS).send({roles: roles}); - } catch (error) { - res.status(Constants.FORBIDDEN).send({error: error as string}); - } + res.status(Constants.SUCCESS).send({roles: roles}); }); -authRouter.get("/roles/", (req: Request, res: Response) => { - try { - const payload: JwtPayload = decodeJwtToken(req.headers.authorization); - res.status(Constants.SUCCESS).send({id: payload.id, roles: payload.roles}); - } catch (error) { - res.status(Constants.FORBIDDEN).send({error: error as string}); - } +authRouter.get("/roles/", verifyJwt, (req: Request, res: Response) => { + const payload: JwtPayload = decodeJwtToken(req.headers.authorization) ; + res.status(Constants.SUCCESS).send({id: payload.id, roles: payload.roles}); }); -authRouter.get("/token/refresh", async (req: Request, res: Response) => { - try { - // Get old data from token - const oldPayload: JwtPayload = decodeJwtToken(req.headers.authorization); - const data: ProfileData = { - id: oldPayload.id, - email: oldPayload.email, - }; +authRouter.get("/token/refresh", verifyJwt, async (_: Request, res: Response) => { + // Get old data from token + const oldPayload: JwtPayload = res.locals.payload as JwtPayload; + const data: ProfileData = { + id: oldPayload.id, + email: oldPayload.email, + }; - // Generate a new payload for the token - let newPayload: JwtPayload | undefined; - await getJwtPayloadFromProfile(oldPayload.provider, data).then((payload: JwtPayload) => { - newPayload = payload; - }); - - // Create and return a new token with the payload - const newToken: string = generateJwtToken(newPayload); - res.status(Constants.SUCCESS).send({token: newToken}); + // Generate a new payload for the token + let newPayload: JwtPayload | undefined; + await getJwtPayloadFromProfile(oldPayload.provider, data).then((payload: JwtPayload) => { + newPayload = payload; + }); - } catch (error) { - res.status(Constants.FORBIDDEN).send({error: error as string}); - } + // Create and return a new token with the payload + const newToken: string = generateJwtToken(newPayload); + res.status(Constants.SUCCESS).send({token: newToken}); }); diff --git a/src/services/user/user-router.ts b/src/services/user/user-router.ts index 5228a2b3..87426fbf 100644 --- a/src/services/user/user-router.ts +++ b/src/services/user/user-router.ts @@ -11,10 +11,9 @@ import { UserFormat } from "./user-formats.js"; import { getUser, updateUser } from "./user-lib.js"; const userRouter: Router = Router(); -userRouter.use(verifyJwt); -userRouter.get("/qr/", (_: Request, res: Response) => { +userRouter.get("/qr/", verifyJwt, (_: Request, res: Response) => { // Return the same payload, but with const payload: JwtPayload = res.locals.payload as JwtPayload; const token: string = generateJwtToken(payload, "20s"); @@ -23,8 +22,8 @@ userRouter.get("/qr/", (_: Request, res: Response) => { }); -userRouter.get("/qr/:USERID", async (req: Request, res: Response) => { - const targetUser: string | undefined = req.query.USERID as string; +userRouter.get("/qr/:USERID", verifyJwt, async (req: Request, res: Response) => { + const targetUser: string | undefined = req.params.USERID as string; // If target user -> redirect to base function if (!targetUser) { @@ -54,15 +53,14 @@ userRouter.get("/qr/:USERID", async (req: Request, res: Response) => { }); -userRouter.get("/:USERID", async (req: Request, res: Response) => { - const targetUser: string | undefined = req.params.USERID; - +userRouter.get("/:USERID", verifyJwt, async (req: Request, res: Response) => { // If no target user, exact same as next route - if (!targetUser) { + if (!req.params.USERID) { res.redirect("/"); - return; } + const targetUser: string = req.params.USERID ?? ""; + // Get payload, and check if authorized const payload: JwtPayload = res.locals.payload as JwtPayload; if (payload.id == targetUser || hasElevatedPerms(payload)) { @@ -78,7 +76,7 @@ userRouter.get("/:USERID", async (req: Request, res: Response) => { }); -userRouter.get("/", async (_: Request, res: Response) => { +userRouter.get("/", verifyJwt, async (_: Request, res: Response) => { // Get payload, return user's values const payload: JwtPayload = res.locals.payload as JwtPayload; const user: UserSchema = await getUser(payload.id); @@ -86,7 +84,7 @@ userRouter.get("/", async (_: Request, res: Response) => { }); -userRouter.post("/", async (req: Request, res: Response) => { +userRouter.post("/", verifyJwt, async (req: Request, res: Response) => { const token: JwtPayload = res.locals.payload as JwtPayload; if (!hasElevatedPerms(token)) { @@ -112,6 +110,4 @@ userRouter.post("/", async (req: Request, res: Response) => { }); - - export default userRouter;