feat(auth): wire login events into OAuth login helper

- Record success login event with risk scoring after OAuth token issuance
- Import login-events repo + risk-scorer into oauth/routes
- Best-effort recording — never blocks OAuth login flow
This commit is contained in:
saravanakumardb1 2026-03-12 11:19:11 -07:00
parent 82d7f157d9
commit 0f4be0c325

View File

@ -23,6 +23,8 @@ import { OAuthGoogleSchema, OAuthMicrosoftSchema, OAuthAppleSchema } from './typ
import type { UserDoc, AuthProviderDoc } from '../types.js';
import * as subscriptionRepo from '../../subscriptions/repository.js';
import * as licenseRepo from '../../licenses/repository.js';
import * as loginEventRepo from '../login-events/repository.js';
import { scoreLoginRisk } from '../login-events/risk-scorer.js';
export async function oauthRoutes(app: FastifyInstance) {
// ── Shared OAuth login helper ─────────────────────────────
@ -176,6 +178,37 @@ export async function oauthRoutes(app: FastifyInstance) {
});
const refreshToken = await jwt.createRefreshToken({ sub: user.id, productId });
// Record OAuth login event (best-effort)
const ip = req.ip || 'unknown';
const method = `oauth_${provider}` as 'oauth_google' | 'oauth_microsoft' | 'oauth_apple';
try {
const recentFailures = await loginEventRepo.countRecentFailures(user.id, 15 * 60 * 1000);
const risk = scoreLoginRisk({
ip,
isNewIp: true,
isNewDevice: true,
isDeviceTrusted: false,
recentFailures,
method,
hourOfDay: new Date().getHours(),
});
await loginEventRepo.record({
id: `le_${crypto.randomUUID()}`,
userId: user.id,
productId,
result: 'success',
method,
riskLevel: risk.level,
riskScore: risk.score,
ip,
userAgent: req.headers['user-agent'] as string | undefined,
riskFlags: risk.flags,
createdAt: new Date().toISOString(),
});
} catch {
/* best-effort */
}
return {
accessToken,
refreshToken,