Basic token verification
This commit is contained in:
parent
7138e02570
commit
ec16301ae3
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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") {
|
||||
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
import { ServerEventListener } from "../../../../util/types";
|
||||
|
||||
export const hi: ServerEventListener<"b"> = {
|
||||
id: "b",
|
||||
callback: (msg, socket) => {
|
||||
// Antibot message
|
||||
}
|
||||
};
|
|
@ -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,8 +60,7 @@ export const hi: ServerEventListener<"hi"> = {
|
|||
};
|
||||
}
|
||||
|
||||
socket.sendArray([
|
||||
{
|
||||
const m = {
|
||||
m: "hi",
|
||||
accountInfo: undefined,
|
||||
permissions: undefined,
|
||||
|
@ -61,7 +72,10 @@ export const hi: ServerEventListener<"hi"> = {
|
|||
},
|
||||
token: generatedToken
|
||||
}
|
||||
]);
|
||||
|
||||
logger.debug("Hi message:", m);
|
||||
|
||||
socket.sendArray([m as ClientEvents["hi"]]);
|
||||
|
||||
socket.gateway.hasProcessedHi = true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue