Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/services/auth/sessionLifecycle.server.ts
T

38 lines
1.9 KiB
TypeScript

import { hashIp, lookupCountry } from "~/modules/ipAddress/services/geoip.server";
import { getClientIPAddress } from "~/utils/server/IpUtils";
import { createUserSession as createServerSessionRow, revokeSessionByToken } from "./sessionStore.server";
// R-P2a S4b — Bruecke zwischen Cookie-Login und dem serverseitigen Session-Store. Additiv:
// das Login-Cookie bleibt der primaere Auth-Mechanismus, parallel wird eine UserSession-Zeile
// gefuehrt, damit Geraeteliste, Revoke und "ueberall abmelden" greifen.
export function extractRawClientIp(request: Request): string | null {
return getClientIPAddress(request.headers)?.toString() ?? null;
}
// AD-22: persistiert KEINE Klartext-IP. Die IP wird gehasht (hashIp, Wiedererkennung "gleiches
// Geraet") und das Land lokal aufgeloest (lookupCountry; die IP verlaesst die Infra nicht).
export async function buildSessionDeviceContext(request: Request): Promise<{ ipHash: string | null; userAgent: string | null; approxLocation: string | null }> {
const rawIp = extractRawClientIp(request);
const country = rawIp ? await lookupCountry(rawIp) : null;
return {
ipHash: rawIp ? hashIp(rawIp) : null,
userAgent: request.headers.get("user-agent"),
approxLocation: country?.countryName ?? null,
};
}
// Beim Login/Signup aufgerufen: legt die Session-Zeile mit (pseudonymisiertem) Geraete-Kontext an und
// liefert den rohen Token zurueck, der ins Cookie wandert. Best-effort: ein Store-Fehler darf den Login
// nicht verhindern (Cookie ist Source-of-Truth fuer die Identitaet).
export async function startServerSession({ request, userId }: { request: Request; userId: string }): Promise<string | null> {
const context = await buildSessionDeviceContext(request);
const { rawToken } = await createServerSessionRow({ userId, ...context });
return rawToken;
}
export async function endServerSession(rawToken: string | undefined | null): Promise<void> {
await revokeSessionByToken(rawToken);
}