api/security: jwt session token
This commit is contained in:
59
api/src/security/jwt.js
Normal file
59
api/src/security/jwt.js
Normal file
@@ -0,0 +1,59 @@
|
||||
import { nanoid } from "nanoid";
|
||||
import { createHmac } from "crypto";
|
||||
|
||||
import { env } from "../config.js";
|
||||
|
||||
const toBase64URL = (b) => Buffer.from(b).toString("base64url");
|
||||
const fromBase64URL = (b) => Buffer.from(b, "base64url").toString();
|
||||
|
||||
const makeHmac = (header, payload) =>
|
||||
createHmac("sha256", env.jwtSecret)
|
||||
.update(`${header}.${payload}`)
|
||||
.digest("base64url");
|
||||
|
||||
export const generate = () => {
|
||||
const exp = new Date().getTime() + env.jwtLifetime * 1000;
|
||||
|
||||
const header = toBase64URL(JSON.stringify({
|
||||
alg: "HS256",
|
||||
typ: "JWT"
|
||||
}));
|
||||
|
||||
const payload = toBase64URL(JSON.stringify({
|
||||
jti: nanoid(3),
|
||||
exp,
|
||||
}));
|
||||
|
||||
const signature = makeHmac(header, payload);
|
||||
|
||||
return {
|
||||
token: `${header}.${payload}.${signature}`,
|
||||
exp,
|
||||
};
|
||||
}
|
||||
|
||||
export const verify = (jwt) => {
|
||||
const [header, payload, signature] = jwt.split(".", 3);
|
||||
const timestamp = new Date().getTime();
|
||||
|
||||
if ([header, payload, signature].join('.') !== jwt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const verifySignature = makeHmac(header, payload);
|
||||
|
||||
if (verifySignature !== signature) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (timestamp >= JSON.parse(fromBase64URL(payload)).exp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export default {
|
||||
generate,
|
||||
verify,
|
||||
}
|
||||
19
api/src/security/turnstile.js
Normal file
19
api/src/security/turnstile.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { env } from "../config.js";
|
||||
|
||||
export const verifyTurnstileToken = async (turnstileResponse, ip) => {
|
||||
const result = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
secret: env.turnstileSecret,
|
||||
response: turnstileResponse,
|
||||
remoteip: ip,
|
||||
}),
|
||||
})
|
||||
.then(r => r.json())
|
||||
.catch(() => {});
|
||||
|
||||
return !!result?.success;
|
||||
}
|
||||
Reference in New Issue
Block a user