First commit
This commit is contained in:
60
backend/src/middleware/auth.js
Normal file
60
backend/src/middleware/auth.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import jwt from "jsonwebtoken";
|
||||
import { JWT_SECRET, TOKEN_TTL } from "../config/auth.js";
|
||||
import User from "../models/User.js";
|
||||
|
||||
/** Issues a session token for an account. */
|
||||
export function signToken(user) {
|
||||
return jwt.sign(
|
||||
{ sub: user._id.toString(), username: user.username },
|
||||
JWT_SECRET,
|
||||
{ expiresIn: TOKEN_TTL }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the `Authorization: Bearer <token>` header and puts the account on
|
||||
* `req.user`; anything else and the request stops here with 401. The message
|
||||
* bodies are what the frontend keys off: a 401 means the session it holds is
|
||||
* no good, so it drops it and asks the person to sign in again.
|
||||
*/
|
||||
export function requireAuth(req, res, next) {
|
||||
const [scheme, token] = String(req.headers.authorization || "").split(" ");
|
||||
|
||||
if (scheme !== "Bearer" || !token) {
|
||||
return res.status(401).json({ message: "Please sign in to do that." });
|
||||
}
|
||||
|
||||
let session;
|
||||
try {
|
||||
session = jwt.verify(token, JWT_SECRET);
|
||||
} catch {
|
||||
return res
|
||||
.status(401)
|
||||
.json({ message: "That session has expired — please sign in again." });
|
||||
}
|
||||
|
||||
req.user = { id: session.sub, username: session.username };
|
||||
next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs after `requireAuth` and lets an admin through alone. The role is read
|
||||
* from the account rather than trusted from the token, so taking it away works
|
||||
* the next time the dashboard is asked for — a token issued while the account
|
||||
* was an admin is no good once it is not.
|
||||
*/
|
||||
export async function requireAdmin(req, res, next) {
|
||||
try {
|
||||
const account = await User.findById(req.user.id);
|
||||
if (!account) {
|
||||
return res.status(401).json({ message: "No such account any more." });
|
||||
}
|
||||
if (account.role !== "admin") {
|
||||
return res.status(403).json({ message: "This is for administrators." });
|
||||
}
|
||||
req.user.role = account.role;
|
||||
next();
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user