diff --git a/src/api/routes/users/#user_id/delete.ts b/src/api/routes/users/#user_id/delete.ts
index 50494a23..be361f18 100644
--- a/src/api/routes/users/#user_id/delete.ts
+++ b/src/api/routes/users/#user_id/delete.ts
@@ -62,7 +62,7 @@ router.post(
select: [...PrivateUserProjection, "data"],
});
- if (!(await InstanceBan.findOne({ where: { user_id: user.id } })))
+ if ((body?.persistInstanceBan ?? true) && !(await InstanceBan.findOne({ where: { user_id: user.id } })))
await InstanceBan.create({ user_id: user.id, reason: body?.reason ?? "<legacy instance ban API - no reason specified>" }).save();
// prevent bugginess with clients - delete all DMs, only having half of the conversation is quite useless anyhow
diff --git a/src/util/util/Token.ts b/src/util/util/Token.ts
index 9e071ed9..0c7e7aa6 100644
--- a/src/util/util/Token.ts
+++ b/src/util/util/Token.ts
@@ -26,11 +26,24 @@ import { existsSync } from "fs";
import { FindManyOptions, FindOptions, FindOptionsRelationByString, FindOptionsSelect, FindOptionsSelectByString, FindOptionsWhere } from "typeorm";
import * as console from "node:console";
-export const JWTOptions: VerifyOptions = { algorithms: ["HS256"] };
+/// Change history:
+/// 0 - Initial version with HS256
+/// 1 - Switched to ES512
+/// 2 - Add version to token payload
+export const CurrentKeyFormatVersion: number = 2;
export type UserTokenData = {
user: User;
- decoded: { id: string; iat: number };
+ legacyVersion?: number;
+ decoded: {
+ id: string;
+ iat: number;
+ ver?: number; // token format version
+ };
+};
+
+export type ParsedUserTokenData = UserTokenData & {
+ legacyVersion?: number;
};
function logAuth(text: string) {
@@ -56,6 +69,8 @@ export const checkToken = (
token = token.replace("Bot ", ""); // there is no bot distinction in sb
token = token.replace("Bearer ", ""); // allow bearer tokens
+ let legacyVersion: number;
+
const validateUser: jwt.VerifyCallback = async (err, out) => {
const decoded = out as UserTokenData["decoded"];
if (err || !decoded) {
@@ -96,8 +111,13 @@ export const checkToken = (
return rejectAndLog(reject, "Invalid Token");
}
- logAuth("validateUser success: " + JSON.stringify({ decoded, user }));
- return resolve({ decoded, user });
+ const result: ParsedUserTokenData = { decoded, user };
+
+ if(legacyVersion !== undefined)
+ result.legacyVersion = legacyVersion;
+
+ logAuth("validateUser success: " + JSON.stringify(result));
+ return resolve(result);
};
const dec = jwt.decode(token, { complete: true });
@@ -105,8 +125,10 @@ export const checkToken = (
logAuth("Decoded token: " + JSON.stringify(dec));
if (dec.header.alg == "HS256" && Config.get().security.jwtSecret !== null) {
- jwt.verify(token, Config.get().security.jwtSecret!, JWTOptions, validateUser);
+ legacyVersion = 0;
+ jwt.verify(token, Config.get().security.jwtSecret!, { algorithms: ["HS256"] }, validateUser);
} else if (dec.header.alg == "ES512") {
+ legacyVersion = 1;
loadOrGenerateKeypair().then((keyPair) => {
jwt.verify(token, keyPair.publicKey, { algorithms: ["ES512"] }, validateUser);
});
@@ -119,7 +141,7 @@ export async function generateToken(id: string) {
return new Promise((res, rej) => {
jwt.sign(
- { id, iat, kid: keyPair.fingerprint },
+ { id, iat, kid: keyPair.fingerprint, ver: CurrentKeyFormatVersion } as UserTokenData["decoded"],
keyPair.privateKey,
{
algorithm: "ES512",
|