Basic token verification

This commit is contained in:
Hri7566 2024-07-27 17:57:12 -04:00
parent 7138e02570
commit ec16301ae3
6 changed files with 77 additions and 34 deletions

View File

@ -34,4 +34,4 @@ tokenAuth: none
# "none" will disable the browser challenge,
# "obf" will sent an obfuscated function to the client,
# and "basic" will just send a simple function that expects a boolean.
browserChallenge: none
browserChallenge: basic

View File

@ -1,5 +1,4 @@
import { createHash, randomBytes } from "crypto";
import env from "./env";
import { createHash, randomBytes } from "crypto"; import env from "./env";
import { spoop_text } from "./helpers";
export function createID() {

View File

@ -3,6 +3,7 @@ import jsonwebtoken from "jsonwebtoken";
import env from "./env";
import { readFileSync } from "fs";
import { Logger } from "./Logger";
import { readUser, updateUser } from "../data/user";
let privkey: string;
@ -32,12 +33,24 @@ export function generateToken(id: string): Promise<string | undefined> | undefin
} else if (config.tokenAuth == "uuid") {
logger.info("Generating UUID token for user " + id + "...");
return new Promise((resolve, reject) => {
return new Promise(async (resolve, reject) => {
let token: string | undefined;
try {
const uuid = crypto.randomUUID();
token = `${id}.${uuid}`;
// Save token in user data
const user = await readUser(id);
if (!user) throw new Error("User not found");
if (!user.tokens) user.tokens = "[]";
const tokens = JSON.parse(user.tokens);
tokens.push(token);
user.tokens = JSON.stringify(tokens);
await updateUser(user.id, user);
} catch (err) {
logger.warn("Token generation failed for user " + id);
reject(err);
@ -52,8 +65,24 @@ export function generateToken(id: string): Promise<string | undefined> | undefin
} else return new Promise(() => undefined);
}
export function verifyToken(token: string) {
return jsonwebtoken.verify(token, privkey, { algorithms: ["RS256"] });
export async function verifyToken(token: string) {
if (config.tokenAuth !== "none") {
// Get tokens from user data
const user = await readUser(token.split(".")[0]);
if (!user) return false;
if (!user.tokens) return false;
const tokens = JSON.parse(user.tokens);
if (!tokens) return false;
// Check if the token is in the list
for (const tok of tokens) {
if (tok === token) return true;
}
}
return false;
}
export async function decryptJWT(token: string) {

View File

@ -120,6 +120,15 @@ export class Socket extends EventEmitter {
this.setNoteQuota(NoteQuota.PARAMS_RIDICULOUS);
this.bindEventListeners();
if (config.browserChallenge == "basic") {
this.sendArray([{
m: "b",
code: `~return true;`
}]);
} else if (config.browserChallenge == "obf") {
}
})();
}

View File

@ -1,8 +0,0 @@
import { ServerEventListener } from "../../../../util/types";
export const hi: ServerEventListener<"b"> = {
id: "b",
callback: (msg, socket) => {
// Antibot message
}
};

View File

@ -1,6 +1,6 @@
import { Logger } from "../../../../util/Logger";
import { generateToken } from "../../../../util/token";
import { ServerEventListener } from "../../../../util/types";
import { generateToken, verifyToken } from "../../../../util/token";
import { ClientEvents, ServerEventListener } from "../../../../util/types";
import { config } from "../../../usersConfig";
const logger = new Logger("Hi handler");
@ -9,9 +9,24 @@ export const hi: ServerEventListener<"hi"> = {
id: "hi",
callback: async (msg, socket) => {
// Handshake message
if (socket.rateLimits)
if (!socket.rateLimits.normal.hi.attempt()) return;
if (socket.gateway.hasProcessedHi) return;
let generatedToken: string | undefined;
// Browser challenge
if (config.browserChallenge == "basic") {
if (typeof msg.code !== "boolean") return;
if (msg.code === true) {
socket.gateway.hasCompletedBrowserChallenge = true;
}
} else if (config.browserChallenge == "obf") {
// TODO
}
// Is the browser challenge enabled and has the user completed it?
if (config.browserChallenge !== "none" && !socket.gateway.hasCompletedBrowserChallenge) return;
@ -24,6 +39,7 @@ export const hi: ServerEventListener<"hi"> = {
// Check if they have passed the browser challenge
// Send the token to the authenticator
// TODO
const verified = await verifyToken(msg.token);
} else {
// Generate a token
generatedToken = await generateToken(socket.getUserID());
@ -33,10 +49,6 @@ export const hi: ServerEventListener<"hi"> = {
logger.debug("token:", generatedToken);
}
if (socket.rateLimits)
if (!socket.rateLimits.normal.hi.attempt()) return;
if (socket.gateway.hasProcessedHi) return;
let part = socket.getParticipant();
if (!part) {
@ -48,20 +60,22 @@ export const hi: ServerEventListener<"hi"> = {
};
}
socket.sendArray([
{
m: "hi",
accountInfo: undefined,
permissions: undefined,
t: Date.now(),
u: {
_id: part._id,
color: part.color,
name: part.name
},
token: generatedToken
}
]);
const m = {
m: "hi",
accountInfo: undefined,
permissions: undefined,
t: Date.now(),
u: {
_id: part._id,
color: part.color,
name: part.name
},
token: generatedToken
}
logger.debug("Hi message:", m);
socket.sendArray([m as ClientEvents["hi"]]);
socket.gateway.hasProcessedHi = true;
}