logout/signup
This commit is contained in:
@@ -57,9 +57,9 @@ export async function refreshJWT(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const tempToExpire = 60 * 15;
|
const toExpire = 60 * 15;
|
||||||
const jwt = generateSignedJWT(user.id, user.permissions, tempToExpire)
|
const jwt = generateSignedJWT(user.id, user.permissions, toExpire)
|
||||||
res.json({ signed_jwt: jwt });
|
res.set("X-New-Access-Token", jwt);
|
||||||
|
|
||||||
// Have to overwrite with new jwt
|
// Have to overwrite with new jwt
|
||||||
// Also I ain't try/catching cause I just made it
|
// Also I ain't try/catching cause I just made it
|
||||||
|
|||||||
+49
-12
@@ -4,6 +4,7 @@ import { eq } from 'drizzle-orm';
|
|||||||
import { users } from '../db/schema.ts';
|
import { users } from '../db/schema.ts';
|
||||||
import express, { Request, Response } from "express";
|
import express, { Request, Response } from "express";
|
||||||
import { generateSignedJWT, base64UrlDecode } from '../helpers/jwt.ts';
|
import { generateSignedJWT, base64UrlDecode } from '../helpers/jwt.ts';
|
||||||
|
import { loadJWT } from '../middleware/loadJWT.ts';
|
||||||
|
|
||||||
const db = drizzle(process.env.DATABASE_URL!);
|
const db = drizzle(process.env.DATABASE_URL!);
|
||||||
const hashSecret = process.env.PASSWORD_HASH_SECRET!;
|
const hashSecret = process.env.PASSWORD_HASH_SECRET!;
|
||||||
@@ -27,6 +28,43 @@ authRouter.get("/login", async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
const [username, password] = decodedHeader.split(":");
|
const [username, password] = decodedHeader.split(":");
|
||||||
|
|
||||||
|
loginUser(username, password, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
authRouter.put("/logout", loadJWT, async (req: Request, res: Response) => {
|
||||||
|
// since login is controlled by a jwt, all we can do here is wipe the refresh_token
|
||||||
|
// frontend will be responsible for clearing temp token from cache/cookies
|
||||||
|
// This endpoint will require a logged in user (valid jwt)
|
||||||
|
const resp = await db
|
||||||
|
.update(users)
|
||||||
|
.set({ refresh_token: null, logged_in: false })
|
||||||
|
.where(eq(users.id, req.jwt.payload.uid));
|
||||||
|
|
||||||
|
res.json(resp);
|
||||||
|
});
|
||||||
|
|
||||||
|
authRouter.post("/signup", async (req: Request, res: Response) => {
|
||||||
|
const { username, password, display_name } = req.body
|
||||||
|
|
||||||
|
const hashedPassword = crypto
|
||||||
|
.createHmac('sha256', hashSecret)
|
||||||
|
.update(`${presalt}${password}${postsalt}`)
|
||||||
|
.digest("base64url");
|
||||||
|
|
||||||
|
await db
|
||||||
|
.insert(users)
|
||||||
|
.values({
|
||||||
|
display_name: display_name,
|
||||||
|
username: username,
|
||||||
|
hashed_password: hashedPassword,
|
||||||
|
permissions: 44
|
||||||
|
});
|
||||||
|
|
||||||
|
loginUser(username, password, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
// because it write the response, has to be last step
|
||||||
|
async function loginUser(username: string, password: string, res: Response) {
|
||||||
const hashedPassword = crypto
|
const hashedPassword = crypto
|
||||||
.createHmac('sha256', hashSecret)
|
.createHmac('sha256', hashSecret)
|
||||||
.update(`${presalt}${password}${postsalt}`)
|
.update(`${presalt}${password}${postsalt}`)
|
||||||
@@ -40,6 +78,12 @@ authRouter.get("/login", async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
const user = potentialUsers[0];
|
const user = potentialUsers[0];
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(401).json({
|
||||||
|
error: "401: Invalid Username",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const calculatedBuff = Buffer.from(hashedPassword);
|
const calculatedBuff = Buffer.from(hashedPassword);
|
||||||
const storedBuff = Buffer.from(user.hashed_password);
|
const storedBuff = Buffer.from(user.hashed_password);
|
||||||
|
|
||||||
@@ -47,20 +91,21 @@ authRouter.get("/login", async (req: Request, res: Response) => {
|
|||||||
crypto.timingSafeEqual(calculatedBuff, storedBuff);
|
crypto.timingSafeEqual(calculatedBuff, storedBuff);
|
||||||
|
|
||||||
if (!match)
|
if (!match)
|
||||||
return res.status(401).json({ error: "401: failed to authenticate username/password" });
|
return res.status(401).json({ error: "401: Failed to authenticate username/password" });
|
||||||
|
|
||||||
// fifteen minutes
|
// fifteen minutes
|
||||||
const tempToExpire = 60 * 15;
|
const tempToExpire = 60 * 15;
|
||||||
const jwt = generateSignedJWT(user.id, user.permissions, tempToExpire)
|
const jwt = generateSignedJWT(user.id, user.permissions, tempToExpire)
|
||||||
|
|
||||||
// 7 days
|
// seven days
|
||||||
const refreshToExpire = 60 * 60 * 24 * 7;
|
const refreshToExpire = 60 * 60 * 24 * 7;
|
||||||
const refreshjwt = generateSignedJWT(user.id, user.permissions, refreshToExpire);
|
const refreshjwt = generateSignedJWT(user.id, user.permissions, refreshToExpire);
|
||||||
|
|
||||||
const resp = await db
|
const resp = await db
|
||||||
.update(users)
|
.update(users)
|
||||||
.set({
|
.set({
|
||||||
refresh_token: refreshjwt
|
refresh_token: refreshjwt,
|
||||||
|
logged_in: true
|
||||||
})
|
})
|
||||||
.where(eq(users.id, user.id));
|
.where(eq(users.id, user.id));
|
||||||
|
|
||||||
@@ -68,12 +113,4 @@ authRouter.get("/login", async (req: Request, res: Response) => {
|
|||||||
signed_jwt: jwt,
|
signed_jwt: jwt,
|
||||||
refresh_resp: resp
|
refresh_resp: resp
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
authRouter.get("/logout", async (req: Request, res: Response) => {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
authRouter.get("/signup", async (req: Request, res: Response) => {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|||||||
Reference in New Issue
Block a user