@focura/auth-core 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -25
- package/dist/index.d.ts +182 -93
- package/dist/index.js +410 -131
- package/dist/index.js.map +1 -1
- package/package.json +23 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @focura/auth-core
|
|
2
2
|
|
|
3
|
-
Production-ready authentication
|
|
3
|
+
Production-ready authentication engine for Node.js backends.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
@@ -19,19 +19,19 @@ Production-ready authentication core for Express.js backends.
|
|
|
19
19
|
## Installation
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
npm install @focura/auth-core
|
|
23
|
-
npm install -D @types/express
|
|
22
|
+
npm install @focura/auth-core ioredis
|
|
24
23
|
```
|
|
25
24
|
|
|
26
25
|
## Quick Start
|
|
27
26
|
|
|
28
27
|
```typescript
|
|
29
|
-
import {
|
|
28
|
+
import { AuthService } from "@focura/auth-core";
|
|
30
29
|
import Redis from "ioredis";
|
|
30
|
+
import fs from "fs";
|
|
31
31
|
|
|
32
32
|
const redis = new Redis(process.env.REDIS_URL!);
|
|
33
33
|
|
|
34
|
-
const auth = new
|
|
34
|
+
const auth = new AuthService({
|
|
35
35
|
redis,
|
|
36
36
|
userStore: {
|
|
37
37
|
findById: (id) => prisma.user.findUnique({ where: { id } }),
|
|
@@ -39,34 +39,147 @@ const auth = new MiddlewareFactory({
|
|
|
39
39
|
update: (id, data) => prisma.user.update({ where: { id }, data }),
|
|
40
40
|
updateEmailVerified: (id, date) => prisma.user.update({ where: { id }, data: { emailVerified: date } }),
|
|
41
41
|
},
|
|
42
|
-
hmacSecret: process.env.
|
|
42
|
+
hmacSecret: process.env.AUTH_SECRET!,
|
|
43
43
|
jwt: {
|
|
44
44
|
privateKey: fs.readFileSync("keys/private.pem", "utf8"),
|
|
45
45
|
publicKey: fs.readFileSync("keys/public.pem", "utf8"),
|
|
46
46
|
},
|
|
47
|
-
cache: {
|
|
48
|
-
get: (key) => redis.get(key).then(JSON.parse),
|
|
49
|
-
set: (key, val, ttl) => redis.setex(key, ttl!, JSON.stringify(val)),
|
|
50
|
-
delete: (key) => redis.del(key),
|
|
51
|
-
},
|
|
52
|
-
auditLogger: {
|
|
53
|
-
log: (event, data) => prisma.auditLog.create({ data: { event, ...data } }),
|
|
54
|
-
},
|
|
55
47
|
});
|
|
48
|
+
```
|
|
56
49
|
|
|
57
|
-
|
|
58
|
-
app.post("/api/v1/auth/exchange", auth.createExchangeHandler());
|
|
59
|
-
app.post("/api/v1/auth/refresh", auth.createRefreshHandler());
|
|
60
|
-
app.post("/api/v1/auth/logout", auth.createLogoutHandler());
|
|
50
|
+
## High-Level API
|
|
61
51
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
52
|
+
### Token Exchange
|
|
53
|
+
|
|
54
|
+
Exchange a HMAC-signed proof for JWT tokens:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
const tokens = await auth.exchange({
|
|
58
|
+
userId: user.id,
|
|
59
|
+
email: user.email,
|
|
60
|
+
role: user.role,
|
|
61
|
+
sessionId: crypto.randomUUID(),
|
|
62
|
+
timestamp: Date.now(),
|
|
63
|
+
signature: hmacSignature,
|
|
65
64
|
});
|
|
66
65
|
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
// tokens.accessToken, tokens.refreshToken, tokens.sseToken, tokens.sessionId
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Verify Token
|
|
70
|
+
|
|
71
|
+
Verify an access token and load the user:
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
const { user, payload } = await auth.verifyToken({
|
|
75
|
+
token: accessToken,
|
|
76
|
+
ipAddress: "192.168.1.1",
|
|
77
|
+
userAgent: "Mozilla/5.0...",
|
|
69
78
|
});
|
|
79
|
+
|
|
80
|
+
// payload.id, payload.email, payload.role, payload.jti, payload.sessionId
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Refresh Tokens
|
|
84
|
+
|
|
85
|
+
Rotate refresh tokens atomically:
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
const newTokens = await auth.refresh({
|
|
89
|
+
refreshToken: currentRefreshToken,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// newTokens.accessToken, newTokens.refreshToken, newTokens.sseToken
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Logout
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// Single session
|
|
99
|
+
await auth.logout({
|
|
100
|
+
userId: user.id,
|
|
101
|
+
sessionId: sessionId,
|
|
102
|
+
accessTokenJti: jti,
|
|
103
|
+
accessToken: token,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// All sessions
|
|
107
|
+
await auth.logout({
|
|
108
|
+
userId: user.id,
|
|
109
|
+
sessionId: sessionId,
|
|
110
|
+
logoutAll: true,
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Two-Factor Authentication
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// Setup — generate secret + URI for QR code
|
|
118
|
+
const { secret, uri } = auth.generateTwoFactor();
|
|
119
|
+
// Display uri as QR code to user, store secret in database
|
|
120
|
+
|
|
121
|
+
// Verify TOTP code
|
|
122
|
+
const valid = await auth.verifyTwoFactor({ token: "123456", secret });
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Session Management
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// List active sessions
|
|
129
|
+
const sessions = await auth.getActiveSessions(userId);
|
|
130
|
+
|
|
131
|
+
// Revoke a specific session
|
|
132
|
+
await auth.revokeSession(userId, sessionId);
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Account Lockout
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// Record failed login attempt
|
|
139
|
+
const result = await auth.recordLoginFailure(email);
|
|
140
|
+
if (result.locked) {
|
|
141
|
+
console.log(`Account locked until ${result.unlocksAt}`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Clear failures on successful login
|
|
145
|
+
await auth.clearLoginFailures(email);
|
|
146
|
+
|
|
147
|
+
// Check if account is locked
|
|
148
|
+
const status = await auth.isAccountLocked(email);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Audit Logging
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
auth.log("WORKSPACE_CREATED", { userId, workspaceId });
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Express Integration
|
|
158
|
+
|
|
159
|
+
For Express.js applications, use `MiddlewareFactory` for HTTP middleware:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { MiddlewareFactory } from "@focura/auth-core";
|
|
163
|
+
|
|
164
|
+
const factory = new MiddlewareFactory(config);
|
|
165
|
+
|
|
166
|
+
// Auth routes
|
|
167
|
+
app.post("/api/v1/auth/exchange", factory.createExchangeHandler());
|
|
168
|
+
app.post("/api/v1/auth/refresh", factory.createRefreshHandler());
|
|
169
|
+
app.post("/api/v1/auth/logout", factory.createLogoutHandler());
|
|
170
|
+
|
|
171
|
+
// Protected routes
|
|
172
|
+
app.get("/api/v1/profile",
|
|
173
|
+
factory.createAuthenticateMiddleware(),
|
|
174
|
+
(req, res) => { res.json({ user: req.user }); }
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
// Role-based access
|
|
178
|
+
app.get("/api/v1/admin",
|
|
179
|
+
factory.createAuthenticateMiddleware(),
|
|
180
|
+
factory.createAuthorizeMiddleware("ADMIN"),
|
|
181
|
+
(req, res) => { res.json({ admin: true }); }
|
|
182
|
+
);
|
|
70
183
|
```
|
|
71
184
|
|
|
72
185
|
## Adapters
|
|
@@ -79,8 +192,7 @@ Works with ioredis or any compatible client:
|
|
|
79
192
|
import Redis from "ioredis";
|
|
80
193
|
const redis = new Redis(process.env.REDIS_URL);
|
|
81
194
|
|
|
82
|
-
|
|
83
|
-
const auth = new MiddlewareFactory({ redis, ... });
|
|
195
|
+
const auth = new AuthService({ redis, ... });
|
|
84
196
|
```
|
|
85
197
|
|
|
86
198
|
### UserStore
|
|
@@ -133,6 +245,34 @@ openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:2048
|
|
|
133
245
|
openssl rsa -in private.pem -pubout -out public.pem
|
|
134
246
|
```
|
|
135
247
|
|
|
248
|
+
## API Hierarchy
|
|
249
|
+
|
|
250
|
+
### Primary API (Recommended)
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import { AuthService } from "@focura/auth-core";
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
The `AuthService` class provides high-level, framework-agnostic authentication operations.
|
|
257
|
+
|
|
258
|
+
### Extension API
|
|
259
|
+
|
|
260
|
+
Interfaces for integrating your infrastructure:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
import type { UserStore, RedisAdapter, CacheAdapter, AuditLogger } from "@focura/auth-core";
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Advanced API
|
|
267
|
+
|
|
268
|
+
Low-level classes for custom integrations:
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
import { TokenManager, SessionManager, TotpManager, AccountLockout } from "@focura/auth-core";
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
These are available but not required for normal application development.
|
|
275
|
+
|
|
136
276
|
## License
|
|
137
277
|
|
|
138
278
|
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -165,6 +165,54 @@ interface SessionMetadata {
|
|
|
165
165
|
type AuditEventType = "LOGIN_SUCCESS" | "LOGIN_FAILED" | "LOGIN_BLOCKED" | "LOGOUT" | "LOGOUT_ALL_DEVICES" | "TOKEN_REFRESHED" | "TOKEN_REVOKED" | "TOKEN_EXPIRED" | "TOKEN_VERSION_MISMATCH" | "TOKEN_REPLAY_DETECTED" | "EXCHANGE_SUCCESS" | "EXCHANGE_FAILED" | "SSE_CONNECTED" | "SSE_DISCONNECTED" | "ACCOUNT_LOCKED" | "TOTP_VERIFIED" | "TOTP_FAILED" | "PERMISSION_DENIED" | "EMAIL_NOT_VERIFIED" | "SESSION_BOUND" | "SESSION_REBOUND" | "SESSION_HIJACK_DETECTED" | "SESSION_TIMEOUT" | "SESSION_REVOKED" | "SESSIONS_REVOKED" | "MAX_SESSIONS_REACHED" | "DEVICE_MISMATCH" | "SUSPICIOUS_IP_CHANGE" | "CSRF_VALIDATION_FAILED" | "UNAUTHORIZED_ACCESS" | "RATE_LIMIT_EXCEEDED" | "MALWARE_DETECTED" | "SUSPICIOUS_ACTIVITY" | "DATA_EXPORT" | "DATA_DELETION" | "SENSITIVE_DATA_ACCESS" | "WORKSPACE_CREATED" | "WORKSPACE_DELETED" | "MEMBER_ADDED" | "MEMBER_REMOVED" | "ROLE_CHANGED" | "SUBSCRIPTION_CREATED" | "SUBSCRIPTION_CANCELLED" | "PAYMENT_FAILED";
|
|
166
166
|
type AuditSeverity = "info" | "warn" | "critical";
|
|
167
167
|
|
|
168
|
+
declare const DEFAULTS: {
|
|
169
|
+
readonly keyPrefix: "focura:";
|
|
170
|
+
readonly issuer: "focura-app";
|
|
171
|
+
readonly audience: "focura-backend";
|
|
172
|
+
readonly accessTokenExpiry: "15m";
|
|
173
|
+
readonly refreshTokenExpiry: "7d";
|
|
174
|
+
readonly sseTokenExpiry: "30s";
|
|
175
|
+
readonly currentVersion: 1;
|
|
176
|
+
readonly maxConcurrentSessions: 5;
|
|
177
|
+
readonly sessionMetadataTtl: number;
|
|
178
|
+
readonly lockoutMaxFailures: 10;
|
|
179
|
+
readonly lockoutSeconds: number;
|
|
180
|
+
readonly lockoutWindowSeconds: number;
|
|
181
|
+
readonly refreshLockTtlSeconds: 45;
|
|
182
|
+
readonly refreshDedupeTtlSeconds: 30;
|
|
183
|
+
readonly revokedSessionTtl: number;
|
|
184
|
+
readonly inactivityTimeout: number;
|
|
185
|
+
readonly absoluteTimeout: number;
|
|
186
|
+
};
|
|
187
|
+
declare function resolveConfig(raw: AuthCoreConfig): {
|
|
188
|
+
keyPrefix: string;
|
|
189
|
+
issuer: string;
|
|
190
|
+
audience: string;
|
|
191
|
+
accessTokenExpiry: string;
|
|
192
|
+
refreshTokenExpiry: string;
|
|
193
|
+
sseTokenExpiry: string;
|
|
194
|
+
currentVersion: number;
|
|
195
|
+
maxConcurrentSessions: number;
|
|
196
|
+
sessionMetadataTtl: number;
|
|
197
|
+
lockoutMaxFailures: number;
|
|
198
|
+
lockoutSeconds: number;
|
|
199
|
+
lockoutWindowSeconds: number;
|
|
200
|
+
inactivityTimeout: number;
|
|
201
|
+
absoluteTimeout: number;
|
|
202
|
+
redis: RedisAdapter;
|
|
203
|
+
userStore: UserStore;
|
|
204
|
+
hmacSecret: string;
|
|
205
|
+
jwt: TokenConfig;
|
|
206
|
+
cache?: CacheAdapter;
|
|
207
|
+
auditLogger?: AuditLogger;
|
|
208
|
+
observability?: ObservabilitySink;
|
|
209
|
+
errors?: ErrorFactory;
|
|
210
|
+
lockout?: LockoutConfig;
|
|
211
|
+
session?: SessionConfig;
|
|
212
|
+
};
|
|
213
|
+
type ResolvedConfig = ReturnType<typeof resolveConfig>;
|
|
214
|
+
declare const AUDIT_SEVERITY: Record<AuditEventType, AuditSeverity>;
|
|
215
|
+
|
|
168
216
|
declare class TokenManager {
|
|
169
217
|
private readonly privateKey;
|
|
170
218
|
private readonly publicKey;
|
|
@@ -228,16 +276,6 @@ declare class TokenRevocation {
|
|
|
228
276
|
isSessionRevoked(sessionId: string): Promise<boolean>;
|
|
229
277
|
}
|
|
230
278
|
|
|
231
|
-
declare class RefreshLock {
|
|
232
|
-
private readonly redis;
|
|
233
|
-
private readonly prefix;
|
|
234
|
-
constructor(redis: RedisAdapter, prefix?: string);
|
|
235
|
-
private lockKey;
|
|
236
|
-
acquire(sessionId: string): Promise<boolean>;
|
|
237
|
-
release(sessionId: string): Promise<void>;
|
|
238
|
-
isLocked(sessionId: string): Promise<boolean>;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
279
|
declare class SessionManager {
|
|
242
280
|
private readonly redis;
|
|
243
281
|
private readonly tokenRevocation;
|
|
@@ -261,40 +299,6 @@ declare class SessionManager {
|
|
|
261
299
|
}>>;
|
|
262
300
|
}
|
|
263
301
|
|
|
264
|
-
declare function looksLikeServerToServerUA(userAgent: string): boolean;
|
|
265
|
-
declare function looksLikeServerToServerRequest(req: {
|
|
266
|
-
headers: Record<string, string | string[] | undefined>;
|
|
267
|
-
}): boolean;
|
|
268
|
-
declare function normalizeUserAgent(userAgent: string): string;
|
|
269
|
-
declare function generateDeviceFingerprint(req: {
|
|
270
|
-
headers: Record<string, string | string[] | undefined>;
|
|
271
|
-
}): string;
|
|
272
|
-
declare function getClientIp(req: {
|
|
273
|
-
ip?: string;
|
|
274
|
-
headers: Record<string, string | string[] | undefined>;
|
|
275
|
-
socket?: {
|
|
276
|
-
remoteAddress?: string;
|
|
277
|
-
};
|
|
278
|
-
}): string;
|
|
279
|
-
declare function createSessionMetadata(req: {
|
|
280
|
-
ip?: string;
|
|
281
|
-
headers: Record<string, string | string[] | undefined>;
|
|
282
|
-
socket?: {
|
|
283
|
-
remoteAddress?: string;
|
|
284
|
-
};
|
|
285
|
-
}): SessionMetadata;
|
|
286
|
-
declare function isPrivateIp(ip: string): boolean;
|
|
287
|
-
declare function validateSessionBinding(req: {
|
|
288
|
-
headers: Record<string, string | string[] | undefined>;
|
|
289
|
-
ip?: string;
|
|
290
|
-
socket?: {
|
|
291
|
-
remoteAddress?: string;
|
|
292
|
-
};
|
|
293
|
-
}, storedMetadata: SessionMetadata): {
|
|
294
|
-
valid: boolean;
|
|
295
|
-
reason?: string;
|
|
296
|
-
};
|
|
297
|
-
|
|
298
302
|
declare class AccountLockout {
|
|
299
303
|
private readonly redis;
|
|
300
304
|
private readonly maxFailures;
|
|
@@ -333,6 +337,139 @@ declare class TotpManager {
|
|
|
333
337
|
verify(token: string, secret: string): Promise<boolean>;
|
|
334
338
|
}
|
|
335
339
|
|
|
340
|
+
interface ExchangeInput {
|
|
341
|
+
userId: string;
|
|
342
|
+
email: string;
|
|
343
|
+
role: string;
|
|
344
|
+
sessionId?: string;
|
|
345
|
+
timestamp: number;
|
|
346
|
+
signature: string;
|
|
347
|
+
}
|
|
348
|
+
interface ExchangeResult extends TokenPair {
|
|
349
|
+
sseToken: string;
|
|
350
|
+
sessionId: string;
|
|
351
|
+
}
|
|
352
|
+
interface VerifyTokenInput {
|
|
353
|
+
token: string;
|
|
354
|
+
ipAddress?: string;
|
|
355
|
+
userAgent?: string;
|
|
356
|
+
}
|
|
357
|
+
interface VerifyTokenResult {
|
|
358
|
+
user: User;
|
|
359
|
+
payload: {
|
|
360
|
+
id: string;
|
|
361
|
+
email: string;
|
|
362
|
+
role: string;
|
|
363
|
+
jti: string;
|
|
364
|
+
sessionId?: string;
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
interface RefreshInput {
|
|
368
|
+
refreshToken: string;
|
|
369
|
+
}
|
|
370
|
+
interface RefreshResult extends TokenPair {
|
|
371
|
+
sseToken: string;
|
|
372
|
+
}
|
|
373
|
+
interface LogoutInput {
|
|
374
|
+
accessToken?: string;
|
|
375
|
+
accessTokenJti?: string;
|
|
376
|
+
userId?: string;
|
|
377
|
+
sessionId?: string;
|
|
378
|
+
logoutAll?: boolean;
|
|
379
|
+
}
|
|
380
|
+
interface TwoFactorSetupResult {
|
|
381
|
+
secret: string;
|
|
382
|
+
uri: string;
|
|
383
|
+
}
|
|
384
|
+
interface TwoFactorVerifyInput {
|
|
385
|
+
token: string;
|
|
386
|
+
secret: string;
|
|
387
|
+
}
|
|
388
|
+
declare class AuthService {
|
|
389
|
+
readonly tokenManager: TokenManager;
|
|
390
|
+
readonly tokenRevocation: TokenRevocation;
|
|
391
|
+
readonly sessionManager: SessionManager;
|
|
392
|
+
readonly accountLockout: AccountLockout;
|
|
393
|
+
readonly totpManager: TotpManager;
|
|
394
|
+
readonly audit: AuditLog;
|
|
395
|
+
readonly errors: ErrorFactory;
|
|
396
|
+
private readonly config;
|
|
397
|
+
private readonly userStore;
|
|
398
|
+
constructor(rawConfig: AuthCoreConfig);
|
|
399
|
+
getConfig(): ResolvedConfig;
|
|
400
|
+
getRedis(): AuthCoreConfig["redis"];
|
|
401
|
+
exchange(input: ExchangeInput): Promise<ExchangeResult>;
|
|
402
|
+
verifyToken(input: VerifyTokenInput): Promise<VerifyTokenResult>;
|
|
403
|
+
refresh(input: RefreshInput): Promise<RefreshResult>;
|
|
404
|
+
logout(input: LogoutInput): Promise<void>;
|
|
405
|
+
getActiveSessions(userId: string): Promise<{
|
|
406
|
+
sessionId: string;
|
|
407
|
+
deviceInfo: string;
|
|
408
|
+
ipAddress?: string;
|
|
409
|
+
lastActivity: string;
|
|
410
|
+
createdAt: string;
|
|
411
|
+
}[]>;
|
|
412
|
+
revokeSession(userId: string, sessionId: string): Promise<void>;
|
|
413
|
+
generateTwoFactor(): TwoFactorSetupResult;
|
|
414
|
+
createTwoFactorUri(secret: string, email: string): string;
|
|
415
|
+
verifyTwoFactor(input: TwoFactorVerifyInput): Promise<boolean>;
|
|
416
|
+
recordLoginFailure(email: string): Promise<{
|
|
417
|
+
locked: boolean;
|
|
418
|
+
unlocksAt?: Date;
|
|
419
|
+
attempts: number;
|
|
420
|
+
}>;
|
|
421
|
+
clearLoginFailures(email: string): Promise<void>;
|
|
422
|
+
isAccountLocked(email: string): Promise<{
|
|
423
|
+
locked: boolean;
|
|
424
|
+
unlocksAt?: Date;
|
|
425
|
+
}>;
|
|
426
|
+
log(event: AuditEventType, data: Record<string, unknown>): void;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
declare class RefreshLock {
|
|
430
|
+
private readonly redis;
|
|
431
|
+
private readonly prefix;
|
|
432
|
+
constructor(redis: RedisAdapter, prefix?: string);
|
|
433
|
+
private lockKey;
|
|
434
|
+
acquire(sessionId: string): Promise<boolean>;
|
|
435
|
+
release(sessionId: string): Promise<void>;
|
|
436
|
+
isLocked(sessionId: string): Promise<boolean>;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
declare function looksLikeServerToServerUA(userAgent: string): boolean;
|
|
440
|
+
declare function looksLikeServerToServerRequest(req: {
|
|
441
|
+
headers: Record<string, string | string[] | undefined>;
|
|
442
|
+
}): boolean;
|
|
443
|
+
declare function normalizeUserAgent(userAgent: string): string;
|
|
444
|
+
declare function generateDeviceFingerprint(req: {
|
|
445
|
+
headers: Record<string, string | string[] | undefined>;
|
|
446
|
+
}): string;
|
|
447
|
+
declare function getClientIp(req: {
|
|
448
|
+
ip?: string;
|
|
449
|
+
headers: Record<string, string | string[] | undefined>;
|
|
450
|
+
socket?: {
|
|
451
|
+
remoteAddress?: string;
|
|
452
|
+
};
|
|
453
|
+
}): string;
|
|
454
|
+
declare function createSessionMetadata(req: {
|
|
455
|
+
ip?: string;
|
|
456
|
+
headers: Record<string, string | string[] | undefined>;
|
|
457
|
+
socket?: {
|
|
458
|
+
remoteAddress?: string;
|
|
459
|
+
};
|
|
460
|
+
}): SessionMetadata;
|
|
461
|
+
declare function isPrivateIp(ip: string): boolean;
|
|
462
|
+
declare function validateSessionBinding(req: {
|
|
463
|
+
headers: Record<string, string | string[] | undefined>;
|
|
464
|
+
ip?: string;
|
|
465
|
+
socket?: {
|
|
466
|
+
remoteAddress?: string;
|
|
467
|
+
};
|
|
468
|
+
}, storedMetadata: SessionMetadata): {
|
|
469
|
+
valid: boolean;
|
|
470
|
+
reason?: string;
|
|
471
|
+
};
|
|
472
|
+
|
|
336
473
|
declare class SessionTimeoutManager implements SessionLifecycle {
|
|
337
474
|
private readonly redis;
|
|
338
475
|
private readonly inactivityTimeout;
|
|
@@ -352,54 +489,6 @@ declare class SessionTimeoutManager implements SessionLifecycle {
|
|
|
352
489
|
updateActivity(sessionId: string): Promise<boolean>;
|
|
353
490
|
}
|
|
354
491
|
|
|
355
|
-
declare const DEFAULTS: {
|
|
356
|
-
readonly keyPrefix: "focura:";
|
|
357
|
-
readonly issuer: "focura-app";
|
|
358
|
-
readonly audience: "focura-backend";
|
|
359
|
-
readonly accessTokenExpiry: "15m";
|
|
360
|
-
readonly refreshTokenExpiry: "7d";
|
|
361
|
-
readonly sseTokenExpiry: "30s";
|
|
362
|
-
readonly currentVersion: 1;
|
|
363
|
-
readonly maxConcurrentSessions: 5;
|
|
364
|
-
readonly sessionMetadataTtl: number;
|
|
365
|
-
readonly lockoutMaxFailures: 10;
|
|
366
|
-
readonly lockoutSeconds: number;
|
|
367
|
-
readonly lockoutWindowSeconds: number;
|
|
368
|
-
readonly refreshLockTtlSeconds: 45;
|
|
369
|
-
readonly refreshDedupeTtlSeconds: 30;
|
|
370
|
-
readonly revokedSessionTtl: number;
|
|
371
|
-
readonly inactivityTimeout: number;
|
|
372
|
-
readonly absoluteTimeout: number;
|
|
373
|
-
};
|
|
374
|
-
declare function resolveConfig(raw: AuthCoreConfig): {
|
|
375
|
-
keyPrefix: string;
|
|
376
|
-
issuer: string;
|
|
377
|
-
audience: string;
|
|
378
|
-
accessTokenExpiry: string;
|
|
379
|
-
refreshTokenExpiry: string;
|
|
380
|
-
sseTokenExpiry: string;
|
|
381
|
-
currentVersion: number;
|
|
382
|
-
maxConcurrentSessions: number;
|
|
383
|
-
sessionMetadataTtl: number;
|
|
384
|
-
lockoutMaxFailures: number;
|
|
385
|
-
lockoutSeconds: number;
|
|
386
|
-
lockoutWindowSeconds: number;
|
|
387
|
-
inactivityTimeout: number;
|
|
388
|
-
absoluteTimeout: number;
|
|
389
|
-
redis: RedisAdapter;
|
|
390
|
-
userStore: UserStore;
|
|
391
|
-
hmacSecret: string;
|
|
392
|
-
jwt: TokenConfig;
|
|
393
|
-
cache?: CacheAdapter;
|
|
394
|
-
auditLogger?: AuditLogger;
|
|
395
|
-
observability?: ObservabilitySink;
|
|
396
|
-
errors?: ErrorFactory;
|
|
397
|
-
lockout?: LockoutConfig;
|
|
398
|
-
session?: SessionConfig;
|
|
399
|
-
};
|
|
400
|
-
type ResolvedConfig = ReturnType<typeof resolveConfig>;
|
|
401
|
-
declare const AUDIT_SEVERITY: Record<AuditEventType, AuditSeverity>;
|
|
402
|
-
|
|
403
492
|
interface AuthRequest {
|
|
404
493
|
user?: {
|
|
405
494
|
id: string;
|
|
@@ -590,4 +679,4 @@ declare class ValidationError extends Error {
|
|
|
590
679
|
|
|
591
680
|
declare const defaultErrors: ErrorFactory;
|
|
592
681
|
|
|
593
|
-
export { AUDIT_SEVERITY, AccountBannedError, AccountLockout, type AuditEventType, AuditLog, type AuditLogger, type AuditSeverity, type AuthCoreConfig, type AuthRequest, BadRequestError, type CacheAdapter, DEFAULTS, type DeviceFingerprint, EmailNotVerifiedError, type ErrorFactory, ForbiddenError, InvalidTokenError, type LockoutConfig, MiddlewareFactory, type ObservabilitySink, type RateLimiterFactory, type RedisAdapter, type RedisPipeline, RefreshLock, type ResolvedConfig, type SessionConfig, SessionHijackError, type SessionLifecycle, SessionManager, type SessionMetadata, SessionTimeoutManager, type TokenConfig, TokenExpiredError, TokenManager, type TokenPair, type TokenPayload, TokenRevocation, TokenRevokedError, TotpManager, UnauthorizedError, type User, type UserStore, ValidationError, type ZodSchema, createSessionMetadata, defaultErrors, exchangeSchema, generateDeviceFingerprint, getClientIp, isPrivateIp, logoutSchema, looksLikeServerToServerRequest, looksLikeServerToServerUA, normalizeUserAgent, refreshSchema, resolveConfig, validateSessionBinding };
|
|
682
|
+
export { AUDIT_SEVERITY, AccountBannedError, AccountLockout, type AuditEventType, AuditLog, type AuditLogger, type AuditSeverity, type AuthCoreConfig, type RefreshResult as AuthRefreshResult, type AuthRequest, AuthService, BadRequestError, type CacheAdapter, DEFAULTS, type DeviceFingerprint, EmailNotVerifiedError, type ErrorFactory, type ExchangeInput, type ExchangeResult, ForbiddenError, InvalidTokenError, type LockoutConfig, type LogoutInput, MiddlewareFactory, type ObservabilitySink, type RateLimiterFactory, type RedisAdapter, type RedisPipeline, type RefreshInput, RefreshLock, type ResolvedConfig, type SessionConfig, SessionHijackError, type SessionLifecycle, SessionManager, type SessionMetadata, SessionTimeoutManager, type TokenConfig, TokenExpiredError, TokenManager, type TokenPair, type TokenPayload, TokenRevocation, TokenRevokedError, TotpManager, type TwoFactorSetupResult, type TwoFactorVerifyInput, UnauthorizedError, type User, type UserStore, ValidationError, type VerifyTokenInput, type VerifyTokenResult, type ZodSchema, createSessionMetadata, defaultErrors, exchangeSchema, generateDeviceFingerprint, getClientIp, isPrivateIp, logoutSchema, looksLikeServerToServerRequest, looksLikeServerToServerUA, normalizeUserAgent, refreshSchema, resolveConfig, validateSessionBinding };
|