Add utils package with Web Crypto password hashing
- Create @reviq/utils package with PBKDF2-SHA256 password hashing compatible with Cloudflare Workers (uses crypto.subtle) - Update api-server and CLI to use new utils package for consistent password hashing format across the codebase - Add pino logging to api-server for better request debugging - Make login request tokens cryptographically secure base58 strings instead of database IDs - Add migration to make login_requests.token non-nullable with unique constraint - Fix RPCLink URL construction for client-side API calls - Add db:codegen script to root package.json Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
setCookie,
|
||||
} from "../../utils/cookies.js";
|
||||
import {
|
||||
generateBase58Token,
|
||||
generateDeviceFingerprint,
|
||||
generateExpiry,
|
||||
} from "../../utils/crypto.js";
|
||||
@@ -59,9 +60,9 @@ export const createLoginRequest = os.auth.createLoginRequest.handler(
|
||||
|
||||
// User doesn't exist - return fake response for anti-enumeration
|
||||
if (!user) {
|
||||
// Generate placeholder token (UUID) for anti-enumeration
|
||||
// Generate placeholder token (base58) for anti-enumeration
|
||||
// This prevents attackers from knowing if an email exists based on response
|
||||
const placeholderToken = crypto.randomUUID();
|
||||
const placeholderToken = generateBase58Token();
|
||||
|
||||
// Set placeholder login request token cookie
|
||||
setCookie(
|
||||
@@ -104,14 +105,16 @@ export const createLoginRequest = os.auth.createLoginRequest.handler(
|
||||
const geo = getGeoInfo(context.reqHeaders);
|
||||
const userAgent = getUserAgent(context.reqHeaders);
|
||||
|
||||
// Create login request
|
||||
// Create login request with secure token
|
||||
const expiresAt = generateExpiry(COOKIE_DURATIONS.LOGIN_REQUEST);
|
||||
const token = generateBase58Token();
|
||||
|
||||
const loginRequest = await context.db
|
||||
await context.db
|
||||
.insertInto("login_requests")
|
||||
.values({
|
||||
user_id: userId,
|
||||
email,
|
||||
token,
|
||||
device_fingerprint: deviceFingerprint,
|
||||
ip_address: geo.ip,
|
||||
city: geo.city,
|
||||
@@ -120,16 +123,13 @@ export const createLoginRequest = os.auth.createLoginRequest.handler(
|
||||
user_agent: userAgent,
|
||||
expires_at: expiresAt,
|
||||
})
|
||||
.returning(["id"])
|
||||
.executeTakeFirstOrThrow();
|
||||
.execute();
|
||||
|
||||
const loginRequestId = loginRequest.id;
|
||||
|
||||
// Set login request token cookie with the real login request ID
|
||||
// Set login request token cookie with the secure token
|
||||
setCookie(
|
||||
context.resHeaders,
|
||||
COOKIE_NAMES.LOGIN_REQUEST_TOKEN,
|
||||
loginRequestId,
|
||||
token,
|
||||
COOKIE_OPTIONS.loginRequest,
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user