Wroclaw
ebf5690519
previously tokens were only like IDs, time based and incrementing counter. An attacker could easily bruteforce them. This patch changes tokens to be completely random. fixes #2
49 lines
1.6 KiB
TypeScript
49 lines
1.6 KiB
TypeScript
import crypto from "node:crypto";
|
|
import { type Session } from "@prisma/client";
|
|
|
|
import Snowflake from "~/utils/snowflake";
|
|
|
|
/** Represents a Session token, without expiry data. */
|
|
export default class SessionToken {
|
|
userId: bigint;
|
|
sessionId: bigint;
|
|
sessionToken: Buffer;
|
|
|
|
constructor(userId: bigint, sessionId?: bigint, sessionToken?: Buffer) {
|
|
this.userId = userId;
|
|
this.sessionId = sessionId ?? new Snowflake().state;
|
|
this.sessionToken = sessionToken ?? crypto.randomBytes(64);
|
|
}
|
|
|
|
/** Creates SessionToken from a string.
|
|
* @param string The strinct to create from.
|
|
* @returns The SessionToken object.
|
|
*/
|
|
static fromString(string: string): SessionToken {
|
|
const parameters = string.split(".");
|
|
return new SessionToken(
|
|
Buffer.from(parameters[0], "base64").readBigUInt64LE(),
|
|
Buffer.from(parameters[1], "base64").readBigUInt64LE(),
|
|
Buffer.from(parameters[2], "base64"),
|
|
);
|
|
}
|
|
|
|
toString(): string {
|
|
const stringUserId = Buffer.copyBytesFrom(new BigUint64Array([this.userId])).toString("base64");
|
|
const stringSessionId = Buffer.copyBytesFrom(new BigUint64Array([this.sessionId])).toString("base64");
|
|
const stringSessionToken = this.sessionToken.toString("base64");
|
|
return `${stringUserId}.${stringSessionId}.${stringSessionToken}`;
|
|
}
|
|
|
|
/** Returns this SessionToken as Prisma object.
|
|
* For use in where parameter.
|
|
* @returns this as prisma object.
|
|
*/
|
|
toPrisma(): Omit<Session, "expiry_date"> {
|
|
return {
|
|
id: this.sessionId,
|
|
userId: this.userId,
|
|
sessionToken: this.sessionToken,
|
|
};
|
|
}
|
|
}
|