mirror of
https://github.com/imputnet/cobalt.git
synced 2025-06-28 09:28:29 +00:00
api: bind session tokens to ip hash
This commit is contained in:
parent
bf5937e336
commit
1f768df4ec
@ -175,7 +175,7 @@ export const runAPI = async (express, app, __dirname, isPrimary = true) => {
|
|||||||
return fail(res, "error.api.auth.jwt.invalid");
|
return fail(res, "error.api.auth.jwt.invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!jwt.verify(token)) {
|
if (!jwt.verify(token, getIP(req, 32))) {
|
||||||
return fail(res, "error.api.auth.jwt.invalid");
|
return fail(res, "error.api.auth.jwt.invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ export const runAPI = async (express, app, __dirname, isPrimary = true) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
res.json(jwt.generate());
|
res.json(jwt.generate(getIP(req, 32)));
|
||||||
} catch {
|
} catch {
|
||||||
return fail(res, "error.api.generic");
|
return fail(res, "error.api.generic");
|
||||||
}
|
}
|
||||||
|
@ -82,14 +82,13 @@ export function normalizeRequest(request) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getIP(req) {
|
export function getIP(req, prefix = 56) {
|
||||||
const strippedIP = req.ip.replace(/^::ffff:/, '');
|
const strippedIP = req.ip.replace(/^::ffff:/, '');
|
||||||
const ip = ipaddr.parse(strippedIP);
|
const ip = ipaddr.parse(strippedIP);
|
||||||
if (ip.kind() === 'ipv4') {
|
if (ip.kind() === 'ipv4') {
|
||||||
return strippedIP;
|
return strippedIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
const prefix = 56;
|
|
||||||
const v6Bytes = ip.toByteArray();
|
const v6Bytes = ip.toByteArray();
|
||||||
v6Bytes.fill(0, prefix / 8);
|
v6Bytes.fill(0, prefix / 8);
|
||||||
|
|
||||||
|
@ -6,12 +6,19 @@ import { env } from "../config.js";
|
|||||||
const toBase64URL = (b) => Buffer.from(b).toString("base64url");
|
const toBase64URL = (b) => Buffer.from(b).toString("base64url");
|
||||||
const fromBase64URL = (b) => Buffer.from(b, "base64url").toString();
|
const fromBase64URL = (b) => Buffer.from(b, "base64url").toString();
|
||||||
|
|
||||||
const makeHmac = (header, payload) =>
|
const makeHmac = (data) => {
|
||||||
createHmac("sha256", env.jwtSecret)
|
return createHmac("sha256", env.jwtSecret)
|
||||||
.update(`${header}.${payload}`)
|
.update(data)
|
||||||
.digest("base64url");
|
.digest("base64url");
|
||||||
|
}
|
||||||
|
|
||||||
const generate = () => {
|
const sign = (header, payload) =>
|
||||||
|
makeHmac(`${header}.${payload}`);
|
||||||
|
|
||||||
|
const getIPHash = (ip) =>
|
||||||
|
makeHmac(ip).slice(0, 8);
|
||||||
|
|
||||||
|
const generate = (ip) => {
|
||||||
const exp = Math.floor(new Date().getTime() / 1000) + env.jwtLifetime;
|
const exp = Math.floor(new Date().getTime() / 1000) + env.jwtLifetime;
|
||||||
|
|
||||||
const header = toBase64URL(JSON.stringify({
|
const header = toBase64URL(JSON.stringify({
|
||||||
@ -21,10 +28,11 @@ const generate = () => {
|
|||||||
|
|
||||||
const payload = toBase64URL(JSON.stringify({
|
const payload = toBase64URL(JSON.stringify({
|
||||||
jti: nanoid(8),
|
jti: nanoid(8),
|
||||||
|
sub: getIPHash(ip),
|
||||||
exp,
|
exp,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const signature = makeHmac(header, payload);
|
const signature = sign(header, payload);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
token: `${header}.${payload}.${signature}`,
|
token: `${header}.${payload}.${signature}`,
|
||||||
@ -32,7 +40,7 @@ const generate = () => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const verify = (jwt) => {
|
const verify = (jwt, ip) => {
|
||||||
const [header, payload, signature] = jwt.split(".", 3);
|
const [header, payload, signature] = jwt.split(".", 3);
|
||||||
const timestamp = Math.floor(new Date().getTime() / 1000);
|
const timestamp = Math.floor(new Date().getTime() / 1000);
|
||||||
|
|
||||||
@ -40,17 +48,16 @@ const verify = (jwt) => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const verifySignature = makeHmac(header, payload);
|
const verifySignature = sign(header, payload);
|
||||||
|
|
||||||
if (verifySignature !== signature) {
|
if (verifySignature !== signature) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timestamp >= JSON.parse(fromBase64URL(payload)).exp) {
|
const data = JSON.parse(fromBase64URL(payload));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return getIPHash(ip) === data.sub
|
||||||
|
&& timestamp <= data.exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
Loading…
Reference in New Issue
Block a user