summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2025-12-16 06:58:45 +0100
committerRory& <root@rory.gay>2025-12-16 07:00:41 +0100
commite98da0ac65de1942a8fd6181e2a7309ec5324b2a (patch)
treed6a55f8b05de2181dcf7c46dd93e433c80431d46 /src
parentMore maybe un-blowing-up (diff)
downloadserver-ts-e98da0ac65de1942a8fd6181e2a7309ec5324b2a.tar.xz
Upate session info
Diffstat (limited to 'src')
-rw-r--r--src/util/util/Token.ts36
1 files changed, 29 insertions, 7 deletions
diff --git a/src/util/util/Token.ts b/src/util/util/Token.ts

index 2e116503..a364fa24 100644 --- a/src/util/util/Token.ts +++ b/src/util/util/Token.ts
@@ -26,6 +26,8 @@ import { existsSync } from "fs"; import { FindManyOptions, FindOptions, FindOptionsRelationByString, FindOptionsSelect, FindOptionsSelectByString, FindOptionsWhere } from "typeorm"; import * as console from "node:console"; import { randomUpperString } from "@spacebar/api"; +import { IpDataClient } from "./networking"; +import { TimeSpan } from "./Timespan"; /// Change history: /// 1 - Initial version with HS256 @@ -63,8 +65,8 @@ export const checkToken = ( ipAddress?: string; fingerprint?: string; }, -): Promise<UserTokenData> => - new Promise((resolve, reject) => { +): Promise<UserTokenData> => { + return new Promise((resolve, reject) => { token = token.replace("Bot ", ""); // there is no bot distinction in sb token = token.replace("Bearer ", ""); // allow bearer tokens @@ -77,17 +79,25 @@ export const checkToken = ( return rejectAndLog(reject, "Invalid Token meow " + err); } - const user = await User.findOne({ - where: { id: decoded.id }, - select: [...(opts?.select || []), "id", "bot", "disabled", "deleted", "rights", "data"], - relations: opts?.relations, - }); + const [user, session] = await Promise.all([ + User.findOne({ + where: { id: decoded.id }, + select: [...(opts?.select || []), "id", "bot", "disabled", "deleted", "rights", "data"], + relations: opts?.relations, + }), + decoded.did ? Session.findOne({ where: { session_id: decoded.did, user_id: decoded.id } }) : undefined, + ]); if (!user) { logAuth("validateUser rejected: User not found"); return rejectAndLog(reject, "User not found"); } + if (decoded.did && !session) { + logAuth("validateUser rejected: Session not found"); + return rejectAndLog(reject, "Invalid Token"); + } + // we need to round it to seconds as it saved as seconds in jwt iat and valid_tokens_since is stored in milliseconds if (decoded.iat * 1000 < new Date(user.data.valid_tokens_since).setSeconds(0, 0)) { logAuth("validateUser rejected: Token not yet valid"); @@ -110,8 +120,19 @@ export const checkToken = ( return rejectAndLog(reject, "Invalid Token"); } + if (session && TimeSpan.fromDates(session.last_seen.getTime(), new Date().getTime()).totalSeconds >= 15) { + session.last_seen = new Date(); + if (opts?.ipAddress && opts?.ipAddress !== session.last_seen_ip) { + session.last_seen_ip = opts.ipAddress; + let ipInfo = await IpDataClient.getIpInfo(opts.ipAddress); + if (ipInfo?.ip) session.last_seen_location = `${ipInfo.emoji_flag} ${ipInfo.postal} ${ipInfo.city}, ${ipInfo.region}, ${ipInfo.country_name}`; + } + await session.save(); + } + const result: UserTokenData = { decoded, + session: session ?? undefined, user, // v1 can be told apart, v2 cant outside of missing device id and version tokenVersion: decoded.ver ?? legacyVersion ?? 2, @@ -136,6 +157,7 @@ export const checkToken = ( }); } else return reject("Invalid token algorithm"); }); +}; export async function generateToken(id: string, isAdminSession: boolean = false) { const iat = Math.floor(Date.now() / 1000);