@azlib/identity 0.2.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.
Files changed (69) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +387 -0
  3. package/dist/errors-BGMwaW5s.d.mts +481 -0
  4. package/dist/errors-BGMwaW5s.d.mts.map +1 -0
  5. package/dist/errors-Bcjx9o6g.cjs +111 -0
  6. package/dist/errors-C2xZAatu.d.cts +481 -0
  7. package/dist/errors-C2xZAatu.d.cts.map +1 -0
  8. package/dist/errors-CEmnZxIn.mjs +66 -0
  9. package/dist/errors-CEmnZxIn.mjs.map +1 -0
  10. package/dist/express.cjs +405 -0
  11. package/dist/express.d.cts +87 -0
  12. package/dist/express.d.cts.map +1 -0
  13. package/dist/express.d.mts +87 -0
  14. package/dist/express.d.mts.map +1 -0
  15. package/dist/express.mjs +401 -0
  16. package/dist/express.mjs.map +1 -0
  17. package/dist/identity-4eP45YIP.cjs +461 -0
  18. package/dist/identity-Bz9RDOvT.mjs +410 -0
  19. package/dist/identity-Bz9RDOvT.mjs.map +1 -0
  20. package/dist/identity-router-DBL20UWT.d.mts +115 -0
  21. package/dist/identity-router-DBL20UWT.d.mts.map +1 -0
  22. package/dist/identity-router-Dib30Waj.d.cts +115 -0
  23. package/dist/identity-router-Dib30Waj.d.cts.map +1 -0
  24. package/dist/identity-service-B9zrvE9z.d.mts +128 -0
  25. package/dist/identity-service-B9zrvE9z.d.mts.map +1 -0
  26. package/dist/identity-service-CLzKx8Z7.d.cts +128 -0
  27. package/dist/identity-service-CLzKx8Z7.d.cts.map +1 -0
  28. package/dist/identity-store-BRRahxcS.d.cts +272 -0
  29. package/dist/identity-store-BRRahxcS.d.cts.map +1 -0
  30. package/dist/identity-store-BRRahxcS.d.mts +272 -0
  31. package/dist/identity-store-BRRahxcS.d.mts.map +1 -0
  32. package/dist/index-CpufYgyn.d.cts +30 -0
  33. package/dist/index-CpufYgyn.d.cts.map +1 -0
  34. package/dist/index-CpufYgyn.d.mts +30 -0
  35. package/dist/index-CpufYgyn.d.mts.map +1 -0
  36. package/dist/index.cjs +18 -0
  37. package/dist/index.d.cts +4 -0
  38. package/dist/index.d.mts +4 -0
  39. package/dist/index.mjs +3 -0
  40. package/dist/logger-Be1wDzBC.cjs +48 -0
  41. package/dist/logger-CcCHJVVe.mjs +33 -0
  42. package/dist/logger-CcCHJVVe.mjs.map +1 -0
  43. package/dist/nestjs.cjs +516 -0
  44. package/dist/nestjs.d.cts +102 -0
  45. package/dist/nestjs.d.cts.map +1 -0
  46. package/dist/nestjs.d.mts +102 -0
  47. package/dist/nestjs.d.mts.map +1 -0
  48. package/dist/nestjs.mjs +500 -0
  49. package/dist/nestjs.mjs.map +1 -0
  50. package/dist/node.cjs +946 -0
  51. package/dist/node.d.cts +260 -0
  52. package/dist/node.d.cts.map +1 -0
  53. package/dist/node.d.mts +260 -0
  54. package/dist/node.d.mts.map +1 -0
  55. package/dist/node.mjs +890 -0
  56. package/dist/node.mjs.map +1 -0
  57. package/dist/test-utils.cjs +169 -0
  58. package/dist/test-utils.d.cts +12 -0
  59. package/dist/test-utils.d.cts.map +1 -0
  60. package/dist/test-utils.d.mts +12 -0
  61. package/dist/test-utils.d.mts.map +1 -0
  62. package/dist/test-utils.mjs +170 -0
  63. package/dist/test-utils.mjs.map +1 -0
  64. package/package.json +92 -0
  65. package/schema/model.ts +100 -0
  66. package/schema/mysql.sql +102 -0
  67. package/schema/postgres.sql +92 -0
  68. package/schema/prisma.schema +122 -0
  69. package/schema/sqlite.sql +92 -0
@@ -0,0 +1,481 @@
1
+ import { c as AuthResult, d as AuthenticatedIdentity, h as IdentityEventType, m as IdentityEvent, r as IdentityStore, s as AccessTokenClaims, x as Permission } from "./identity-store-BRRahxcS.cjs";
2
+
3
+ //#region core/authorization.d.ts
4
+ /**
5
+ * Context passed to authorization checks. `resource` is an opaque consumer-supplied
6
+ * object (e.g. a loaded document) used by ownership/relationship policies.
7
+ */
8
+ interface AuthorizationContext<TResource = unknown> {
9
+ principal: AuthenticatedIdentity;
10
+ /** The action being attempted, typically a permission string. */
11
+ action: string;
12
+ /** The target resource, if any. */
13
+ resource?: TResource;
14
+ }
15
+ /**
16
+ * A policy rule returns:
17
+ * - `true` to allow,
18
+ * - `false`/`undefined` to abstain (deny-by-default unless another rule allows),
19
+ * It must never throw for normal "denied" outcomes.
20
+ */
21
+ type PolicyRule<TResource = unknown> = (context: AuthorizationContext<TResource>) => boolean | undefined | Promise<boolean | undefined>;
22
+ /** A named requirement combining a required permission and optional ownership policy. */
23
+ interface AuthorizationRequirement<TResource = unknown> {
24
+ /** Permission the principal must hold. Omit to rely solely on policies. */
25
+ permission?: Permission;
26
+ /** Optional ownership/relationship rule evaluated against the resource. */
27
+ policy?: PolicyRule<TResource>;
28
+ }
29
+ /** Result of an authorization decision. */
30
+ interface AuthorizationDecision {
31
+ allowed: boolean;
32
+ /** Non-sensitive reason for diagnostics/audit. */
33
+ reason: string;
34
+ }
35
+ /**
36
+ * Evaluates a requirement using deny-by-default semantics:
37
+ * 1. If a `permission` is required and the principal lacks it, deny.
38
+ * 2. If a `policy` is provided, it must return `true` to allow.
39
+ * 3. If neither is provided, deny (nothing explicitly granted access).
40
+ */
41
+ declare function evaluateAuthorization<TResource = unknown>(requirement: AuthorizationRequirement<TResource>, context: AuthorizationContext<TResource>): Promise<AuthorizationDecision>;
42
+ /** Convenience boolean form of {@link evaluateAuthorization}. */
43
+ declare function isAuthorized<TResource = unknown>(requirement: AuthorizationRequirement<TResource>, context: AuthorizationContext<TResource>): Promise<boolean>;
44
+ //#endregion
45
+ //#region core/logger.d.ts
46
+ /**
47
+ * Pluggable logger interface for `@azlib/identity`.
48
+ *
49
+ * The package uses this interface for request/response logging in the Express router and
50
+ * for operational messages throughout the module. Consumers can hook any structured
51
+ * logging library (Winston, Pino, Bunyan, etc.) by implementing this interface.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * import pino from "pino";
56
+ *
57
+ * const logger = pino();
58
+ * createIdentityRouter(service, { logger });
59
+ * ```
60
+ */
61
+ interface IdentityLogger {
62
+ debug(message: string, meta?: Record<string, unknown>): void;
63
+ info(message: string, meta?: Record<string, unknown>): void;
64
+ warn(message: string, meta?: Record<string, unknown>): void;
65
+ error(message: string, meta?: Record<string, unknown>): void;
66
+ }
67
+ /**
68
+ * Default logger that writes to the Node.js console with an `[identity]` prefix.
69
+ * Used when no custom logger is provided.
70
+ */
71
+ declare const consoleLogger: IdentityLogger;
72
+ /** No-op logger. Pass `false` or `noopLogger` to disable all identity logging. */
73
+ declare const noopLogger: IdentityLogger;
74
+ /**
75
+ * Resolves an `IdentityLogger | false | undefined` to a concrete `IdentityLogger`.
76
+ *
77
+ * - `false` → {@link noopLogger}
78
+ * - `undefined` → {@link consoleLogger}
79
+ * - anything else → returned as-is
80
+ */
81
+ declare function resolveLogger(logger?: IdentityLogger | false): IdentityLogger;
82
+ //#endregion
83
+ //#region core/notification.d.ts
84
+ /**
85
+ * Pluggable notification service interface.
86
+ *
87
+ * Implement this to send emails and SMS messages from your own infrastructure
88
+ * (SMTP, SendGrid, Twilio, etc.). The library only defines the interface; consumers
89
+ * provide the concrete implementation.
90
+ *
91
+ * Pass the implementation to `createIdentityService` via the `notifications` config key.
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * import { createIdentityService } from "@azlib/identity/node";
96
+ * import type { NotificationService } from "@azlib/identity/node";
97
+ *
98
+ * const notifications: NotificationService = {
99
+ * async sendEmailVerification({ email, token }) {
100
+ * await mailer.send({
101
+ * to: email,
102
+ * subject: "Verify your email",
103
+ * text: `Click to verify: https://example.com/verify-email?token=${token}`,
104
+ * });
105
+ * },
106
+ * async sendPasswordReset({ email, token }) {
107
+ * await mailer.send({
108
+ * to: email,
109
+ * subject: "Reset your password",
110
+ * text: `Click to reset: https://example.com/reset-password?token=${token}`,
111
+ * });
112
+ * },
113
+ * };
114
+ *
115
+ * const identity = createIdentityService({ ..., notifications }, store);
116
+ * ```
117
+ */
118
+ /** Parameters passed to {@link NotificationService.sendEmailVerification}. */
119
+ interface EmailVerificationParams {
120
+ email: string;
121
+ displayName: string | null;
122
+ /**
123
+ * The raw verification token. Embed it in a URL, e.g.
124
+ * `https://example.com/verify-email?token=${token}`.
125
+ */
126
+ token: string;
127
+ }
128
+ /** Parameters passed to {@link NotificationService.sendPasswordReset}. */
129
+ interface PasswordResetParams {
130
+ email: string;
131
+ displayName: string | null;
132
+ /**
133
+ * The raw reset token. Embed it in a URL, e.g.
134
+ * `https://example.com/reset-password?token=${token}`.
135
+ */
136
+ token: string;
137
+ }
138
+ /** Parameters passed to {@link NotificationService.sendTwoFactorCode}. */
139
+ interface TwoFactorSmsParams {
140
+ phoneNumber: string;
141
+ /** 6-digit TOTP code to include in the SMS message. */
142
+ code: string;
143
+ }
144
+ /**
145
+ * Notification service for identity-related messages.
146
+ *
147
+ * All methods are optional — only implement the ones your application needs.
148
+ * The library calls each method only when the corresponding feature is active.
149
+ */
150
+ interface NotificationService {
151
+ /** Called after a user registers or explicitly requests a new verification email. */
152
+ sendEmailVerification?(params: EmailVerificationParams): Promise<void>;
153
+ /** Called when a password reset is requested. */
154
+ sendPasswordReset?(params: PasswordResetParams): Promise<void>;
155
+ /** Called to deliver a 2FA code via SMS (when using SMS-based out-of-band 2FA). */
156
+ sendTwoFactorCode?(params: TwoFactorSmsParams): Promise<void>;
157
+ }
158
+ //#endregion
159
+ //#region core/config.d.ts
160
+ /**
161
+ * Pluggable override points for advanced consumers. All are optional; sensible Node
162
+ * defaults are supplied by the runtime entry (`@azlib/identity/node`).
163
+ */
164
+ interface IdentityOverrides {
165
+ /** Returns the current time. Override in tests for deterministic clocks. */
166
+ now?: () => Date;
167
+ /** Generates a unique id (user ids, session ids). Defaults to `crypto.randomUUID`. */
168
+ generateId?: () => string;
169
+ /**
170
+ * Lifecycle hook invoked for every audit event (registration, login, refresh, etc.).
171
+ * Use it to forward events to your own logging/analytics pipeline. It must never throw
172
+ * for normal operation; failures are swallowed so auditing cannot break auth flows.
173
+ */
174
+ onEvent?: (event: IdentityEvent) => void | Promise<void>;
175
+ }
176
+ /** Account lockout policy applied after repeated failed logins. */
177
+ interface LockoutConfig {
178
+ /**
179
+ * How many consecutive failed login attempts are allowed before the account is
180
+ * temporarily locked. Set to 0 to disable lockout. Default 10.
181
+ */
182
+ maxFailedAttempts: number;
183
+ /**
184
+ * How long (in seconds) a locked account is blocked before automatic unlock.
185
+ * Default 900 (15 minutes). Set to 0 for permanent lock (manual unlock required).
186
+ */
187
+ durationSeconds: number;
188
+ }
189
+ /** Raw configuration accepted from consumers. */
190
+ interface IdentityConfigInput {
191
+ /**
192
+ * Secret used to sign and verify access tokens (HMAC). Must be at least 32 characters.
193
+ * Provide via environment, never hardcode.
194
+ */
195
+ accessTokenSecret: string;
196
+ /** Access-token lifetime in seconds. Default 900 (15 minutes). */
197
+ accessTokenTtlSeconds?: number;
198
+ /** Refresh-token lifetime in seconds. Default 1209600 (14 days). */
199
+ refreshTokenTtlSeconds?: number;
200
+ /** Token issuer (`iss`). Default `azlib-identity`. */
201
+ issuer?: string;
202
+ /** Token audience (`aud`). Optional. */
203
+ audience?: string;
204
+ /** scrypt cost parameter `N`. Default 16384. */
205
+ passwordScryptCost?: number;
206
+ /**
207
+ * Account lockout policy. Omit or set `maxFailedAttempts: 0` to disable. Default: 10
208
+ * attempts, 15-minute lockout.
209
+ */
210
+ lockout?: Partial<LockoutConfig>;
211
+ /**
212
+ * Pluggable notification service for email verification, password reset, and SMS 2FA.
213
+ * Omit if you do not need these features.
214
+ */
215
+ notifications?: NotificationService;
216
+ /**
217
+ * Logger used throughout the package. Pass your own `IdentityLogger` to route
218
+ * diagnostic output to Winston, Pino, or any other provider. Pass `false` to silence
219
+ * all logging. Defaults to a console-based logger when omitted.
220
+ */
221
+ logger?: IdentityLogger | false;
222
+ /** Override points for clock and id generation. */
223
+ overrides?: IdentityOverrides;
224
+ }
225
+ /** Fully resolved, validated configuration used internally. */
226
+ interface IdentityConfig {
227
+ accessTokenSecret: string;
228
+ accessTokenTtlSeconds: number;
229
+ refreshTokenTtlSeconds: number;
230
+ issuer: string;
231
+ audience: string | undefined;
232
+ passwordScryptCost: number;
233
+ lockout: LockoutConfig;
234
+ notifications: NotificationService | undefined;
235
+ /** Resolved logger; never `false` — `false` becomes {@link noopLogger}. */
236
+ logger: IdentityLogger;
237
+ now: () => Date;
238
+ generateId: () => string;
239
+ onEvent: ((event: IdentityEvent) => void | Promise<void>) | undefined;
240
+ }
241
+ /**
242
+ * Validates and applies defaults to consumer-provided configuration.
243
+ * Throws {@link IdentityConfigError} when required values are missing or invalid.
244
+ */
245
+ declare function resolveIdentityConfig(input: IdentityConfigInput): IdentityConfig;
246
+ //#endregion
247
+ //#region core/audit.d.ts
248
+ /**
249
+ * Thin auditing helper. Persists events through the store's optional `recordEvent` hook
250
+ * when present and never throws — auditing must not break the primary auth flow.
251
+ *
252
+ * Metadata is restricted to non-sensitive scalars; never pass passwords or raw tokens.
253
+ */
254
+ interface AuditLogger {
255
+ record(type: IdentityEventType, userId: string | null, metadata?: IdentityEvent["metadata"]): Promise<void>;
256
+ }
257
+ declare function createAuditLogger(store: IdentityStore, now: () => Date, onEvent?: (event: IdentityEvent) => void | Promise<void>): AuditLogger;
258
+ //#endregion
259
+ //#region core/token-service.d.ts
260
+ /**
261
+ * Issues and verifies short-lived HS256 access tokens (via `jose`) and generates the
262
+ * opaque refresh tokens whose hashes are stored server-side.
263
+ */
264
+ interface TokenService {
265
+ issueAccessToken(userId: string, authVersion: number): Promise<{
266
+ token: string;
267
+ expiresAt: Date;
268
+ }>;
269
+ verifyAccessToken(token: string): Promise<AccessTokenClaims>;
270
+ /**
271
+ * Creates a refresh token bound to a session id. The id prefix lets the server look up
272
+ * the session, while only the hash of the full token is stored.
273
+ */
274
+ createRefreshToken(sessionId: string): {
275
+ token: string;
276
+ hash: string;
277
+ };
278
+ /** Extracts the session id encoded in a refresh token, or null if malformed. */
279
+ parseSessionId(token: string): string | null;
280
+ /** Hashes a presented refresh token for comparison with the stored hash. */
281
+ hashRefreshToken(token: string): string;
282
+ }
283
+ declare function createTokenService(config: IdentityConfig): TokenService;
284
+ //#endregion
285
+ //#region core/session-state.d.ts
286
+ /** Dependencies shared by the register/login/refresh flows. */
287
+ interface SessionDeps {
288
+ config: IdentityConfig;
289
+ store: IdentityStore;
290
+ tokenService: TokenService;
291
+ }
292
+ //#endregion
293
+ //#region core/oauth/oauth-provider.d.ts
294
+ /**
295
+ * Framework-agnostic OAuth 2.0 / OpenID Connect provider interface.
296
+ *
297
+ * Implement this interface to add any OAuth2/OIDC provider. Pre-built implementations
298
+ * for Google and Microsoft are exported from `@azlib/identity/node`.
299
+ */
300
+ /** Tokens received from an OAuth2 token endpoint. */
301
+ interface OAuthTokens {
302
+ accessToken: string;
303
+ /** OIDC identity token (JWT). Present for OpenID Connect providers. */
304
+ idToken?: string;
305
+ tokenType: string;
306
+ /** Lifetime in seconds. */
307
+ expiresIn: number;
308
+ refreshToken?: string;
309
+ scope?: string;
310
+ }
311
+ /**
312
+ * Normalized user information extracted from the provider after a successful
313
+ * authorization flow.
314
+ */
315
+ interface OAuthUserInfo {
316
+ /** The provider's stable user identifier (`sub` in OIDC). */
317
+ providerUserId: string;
318
+ email: string | null;
319
+ /** Whether the provider has verified the email address. */
320
+ emailVerified: boolean;
321
+ displayName: string | null;
322
+ }
323
+ /** Parameters passed to {@link OAuthProvider.buildAuthorizationUrl}. */
324
+ interface BuildAuthUrlParams {
325
+ /** The URI the provider will redirect to after authorization. */
326
+ redirectUri: string;
327
+ /**
328
+ * An opaque value used to prevent CSRF attacks. Generate with `crypto.randomUUID()` or
329
+ * similar and verify it matches when handling the callback.
330
+ */
331
+ state: string;
332
+ /** Override the default scopes for this request. */
333
+ scopes?: string[];
334
+ }
335
+ /** Parameters passed to {@link OAuthProvider.exchangeCode}. */
336
+ interface ExchangeCodeParams {
337
+ code: string;
338
+ redirectUri: string;
339
+ }
340
+ /**
341
+ * Describes a single OAuth2 / OpenID Connect provider. Implement this interface to
342
+ * plug in any authorization server.
343
+ */
344
+ interface OAuthProvider {
345
+ /**
346
+ * Unique, lowercase identifier for this provider, e.g. `"google"` or `"microsoft"`.
347
+ * Used as the `provider` discriminator on {@link OAuthLinkedAccount}.
348
+ */
349
+ readonly name: string;
350
+ /**
351
+ * Builds the full authorization URL the user should be redirected to. The caller is
352
+ * responsible for storing `state` (e.g. in a signed cookie) and verifying it on
353
+ * callback to prevent CSRF.
354
+ */
355
+ buildAuthorizationUrl(params: BuildAuthUrlParams): string;
356
+ /**
357
+ * Exchanges an authorization code (from the callback) for provider tokens. Must only
358
+ * be called server-side — never expose `clientSecret` to the browser.
359
+ */
360
+ exchangeCode(params: ExchangeCodeParams): Promise<OAuthTokens>;
361
+ /**
362
+ * Fetches or extracts the authenticated user's info from the provider tokens. Called
363
+ * after a successful `exchangeCode`.
364
+ */
365
+ fetchUserInfo(tokens: OAuthTokens): Promise<OAuthUserInfo>;
366
+ }
367
+ //#endregion
368
+ //#region core/oauth/oauth-service.d.ts
369
+ /** Result of {@link OAuthService.buildAuthorizationUrl}. */
370
+ interface OAuthAuthorizationUrl {
371
+ /** The full provider authorization URL to redirect the user to. */
372
+ url: string;
373
+ /**
374
+ * An opaque CSRF-prevention state value. Store this in a signed cookie or server
375
+ * session and pass it as `expectedState` when calling {@link OAuthService.handleCallback}.
376
+ */
377
+ state: string;
378
+ }
379
+ /** Parameters for {@link OAuthService.handleCallback}. */
380
+ interface OAuthCallbackParams {
381
+ /** The authorization code received from the provider callback query string. */
382
+ code: string;
383
+ /** The `state` value received from the provider callback query string. */
384
+ state: string;
385
+ /**
386
+ * The expected state value previously returned by {@link OAuthService.buildAuthorizationUrl}.
387
+ * The callback will be rejected when they do not match (CSRF protection).
388
+ */
389
+ expectedState: string;
390
+ /** The same redirect URI that was used in the authorization request. */
391
+ redirectUri: string;
392
+ /** Optional scopes to override for this callback's code exchange. */
393
+ scopes?: string[];
394
+ }
395
+ /** The OAuth2 / OIDC surface of the identity service. */
396
+ interface OAuthService {
397
+ /** Returns the registered provider names, e.g. `["google", "microsoft"]`. */
398
+ readonly providers: readonly string[];
399
+ /**
400
+ * Builds the authorization URL for the given provider. Redirect the user's browser to
401
+ * the returned `url`, then store `state` for later verification.
402
+ */
403
+ buildAuthorizationUrl(providerName: string, redirectUri: string, scopes?: string[]): OAuthAuthorizationUrl;
404
+ /**
405
+ * Handles the provider callback after user consent. Verifies state, exchanges the code
406
+ * for tokens, resolves or provisions a local user, and returns a full auth result.
407
+ *
408
+ * Throws {@link OAuthProviderNotFoundError} for unknown providers.
409
+ * Throws a generic {@link IdentityError} when state mismatches (CSRF guard).
410
+ */
411
+ handleCallback(providerName: string, params: OAuthCallbackParams): Promise<AuthResult>;
412
+ }
413
+ /** Thrown when an OAuth operation targets an unregistered provider name. */
414
+ declare class OAuthProviderNotFoundError extends Error {
415
+ constructor(providerName: string);
416
+ }
417
+ /** Thrown when the callback state does not match the expected state (CSRF guard). */
418
+ declare class OAuthStateMismatchError extends Error {
419
+ constructor();
420
+ }
421
+ /** Dependencies for {@link createOAuthService}. */
422
+ interface OAuthServiceDeps {
423
+ providers: readonly OAuthProvider[];
424
+ config: IdentityConfig;
425
+ store: IdentityStore;
426
+ sessionDeps: SessionDeps;
427
+ audit: AuditLogger;
428
+ }
429
+ /**
430
+ * Creates the OAuth2 / OIDC service. Wire into the identity service by passing configured
431
+ * provider instances (e.g. `createGoogleOAuthProvider(...)`) to the `oauth.providers` list
432
+ * in {@link IdentityConfigInput}.
433
+ */
434
+ declare function createOAuthService(deps: OAuthServiceDeps): OAuthService;
435
+ //#endregion
436
+ //#region core/errors.d.ts
437
+ /**
438
+ * Error types for `@azlib/identity`.
439
+ *
440
+ * Authentication failures intentionally use a single generic message so callers cannot
441
+ * distinguish "unknown user" from "wrong password", which mitigates account enumeration.
442
+ */
443
+ /** Base class for all identity errors. */
444
+ declare class IdentityError extends Error {
445
+ /** Stable machine-readable code for programmatic handling. */
446
+ readonly code: string;
447
+ /** Suggested HTTP status for transport adapters. */
448
+ readonly statusCode: number;
449
+ constructor(code: string, message: string, statusCode: number);
450
+ }
451
+ /** Configuration is missing or invalid. */
452
+ declare class IdentityConfigError extends IdentityError {
453
+ constructor(message: string);
454
+ }
455
+ /** Generic credential failure. Used for unknown user AND wrong password alike. */
456
+ declare class InvalidCredentialsError extends IdentityError {
457
+ constructor();
458
+ }
459
+ /** A registration was attempted for an email that already exists. */
460
+ declare class EmailAlreadyRegisteredError extends IdentityError {
461
+ constructor();
462
+ }
463
+ /** The provided access token is missing, malformed, expired, or stale. */
464
+ declare class InvalidTokenError extends IdentityError {
465
+ constructor(message?: string);
466
+ }
467
+ /** No authenticated principal is present on the request. */
468
+ declare class UnauthenticatedError extends IdentityError {
469
+ constructor(message?: string);
470
+ }
471
+ /** The authenticated principal is not permitted to perform the action. */
472
+ declare class ForbiddenError extends IdentityError {
473
+ constructor(message?: string);
474
+ }
475
+ /** The user account is disabled or locked. */
476
+ declare class AccountUnavailableError extends IdentityError {
477
+ constructor(message?: string);
478
+ }
479
+ //#endregion
480
+ export { resolveIdentityConfig as A, AuthorizationDecision as B, createTokenService as C, IdentityConfigInput as D, IdentityConfig as E, IdentityLogger as F, PolicyRule as H, consoleLogger as I, noopLogger as L, NotificationService as M, PasswordResetParams as N, IdentityOverrides as O, TwoFactorSmsParams as P, resolveLogger as R, TokenService as S, createAuditLogger as T, evaluateAuthorization as U, AuthorizationRequirement as V, isAuthorized as W, ExchangeCodeParams as _, IdentityError as a, OAuthUserInfo as b, UnauthenticatedError as c, OAuthProviderNotFoundError as d, OAuthService as f, BuildAuthUrlParams as g, createOAuthService as h, IdentityConfigError as i, EmailVerificationParams as j, LockoutConfig as k, OAuthAuthorizationUrl as l, OAuthStateMismatchError as m, EmailAlreadyRegisteredError as n, InvalidCredentialsError as o, OAuthServiceDeps as p, ForbiddenError as r, InvalidTokenError as s, AccountUnavailableError as t, OAuthCallbackParams as u, OAuthProvider as v, AuditLogger as w, SessionDeps as x, OAuthTokens as y, AuthorizationContext as z };
481
+ //# sourceMappingURL=errors-C2xZAatu.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors-C2xZAatu.d.cts","names":[],"sources":["../core/authorization.ts","../core/logger.ts","../core/notification.ts","../core/config.ts","../core/audit.ts","../core/token-service.ts","../core/session-state.ts","../core/oauth/oauth-provider.ts","../core/oauth/oauth-service.ts","../core/errors.ts"],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ //#region core/errors.ts
2
+ /**
3
+ * Error types for `@azlib/identity`.
4
+ *
5
+ * Authentication failures intentionally use a single generic message so callers cannot
6
+ * distinguish "unknown user" from "wrong password", which mitigates account enumeration.
7
+ */
8
+ /** Base class for all identity errors. */
9
+ var IdentityError = class extends Error {
10
+ /** Stable machine-readable code for programmatic handling. */
11
+ code;
12
+ /** Suggested HTTP status for transport adapters. */
13
+ statusCode;
14
+ constructor(code, message, statusCode) {
15
+ super(message);
16
+ this.name = new.target.name;
17
+ this.code = code;
18
+ this.statusCode = statusCode;
19
+ }
20
+ };
21
+ /** Configuration is missing or invalid. */
22
+ var IdentityConfigError = class extends IdentityError {
23
+ constructor(message) {
24
+ super("identity/config-invalid", message, 500);
25
+ }
26
+ };
27
+ /** Generic credential failure. Used for unknown user AND wrong password alike. */
28
+ var InvalidCredentialsError = class extends IdentityError {
29
+ constructor() {
30
+ super("identity/invalid-credentials", "Invalid email or password.", 401);
31
+ }
32
+ };
33
+ /** A registration was attempted for an email that already exists. */
34
+ var EmailAlreadyRegisteredError = class extends IdentityError {
35
+ constructor() {
36
+ super("identity/email-already-registered", "An account with this email already exists.", 409);
37
+ }
38
+ };
39
+ /** The provided access token is missing, malformed, expired, or stale. */
40
+ var InvalidTokenError = class extends IdentityError {
41
+ constructor(message = "Authentication token is invalid or expired.") {
42
+ super("identity/invalid-token", message, 401);
43
+ }
44
+ };
45
+ /** No authenticated principal is present on the request. */
46
+ var UnauthenticatedError = class extends IdentityError {
47
+ constructor(message = "Authentication is required.") {
48
+ super("identity/unauthenticated", message, 401);
49
+ }
50
+ };
51
+ /** The authenticated principal is not permitted to perform the action. */
52
+ var ForbiddenError = class extends IdentityError {
53
+ constructor(message = "You do not have permission to perform this action.") {
54
+ super("identity/forbidden", message, 403);
55
+ }
56
+ };
57
+ /** The user account is disabled or locked. */
58
+ var AccountUnavailableError = class extends IdentityError {
59
+ constructor(message = "This account is not available.") {
60
+ super("identity/account-unavailable", message, 403);
61
+ }
62
+ };
63
+ //#endregion
64
+ export { IdentityError as a, UnauthenticatedError as c, IdentityConfigError as i, EmailAlreadyRegisteredError as n, InvalidCredentialsError as o, ForbiddenError as r, InvalidTokenError as s, AccountUnavailableError as t };
65
+
66
+ //# sourceMappingURL=errors-CEmnZxIn.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors-CEmnZxIn.mjs","names":[],"sources":["../core/errors.ts"],"sourcesContent":["/**\n * Error types for `@azlib/identity`.\n *\n * Authentication failures intentionally use a single generic message so callers cannot\n * distinguish \"unknown user\" from \"wrong password\", which mitigates account enumeration.\n */\n\n/** Base class for all identity errors. */\nexport class IdentityError extends Error {\n /** Stable machine-readable code for programmatic handling. */\n readonly code: string;\n /** Suggested HTTP status for transport adapters. */\n readonly statusCode: number;\n\n constructor(code: string, message: string, statusCode: number) {\n super(message);\n this.name = new.target.name;\n this.code = code;\n this.statusCode = statusCode;\n }\n}\n\n/** Configuration is missing or invalid. */\nexport class IdentityConfigError extends IdentityError {\n constructor(message: string) {\n super(\"identity/config-invalid\", message, 500);\n }\n}\n\n/** Generic credential failure. Used for unknown user AND wrong password alike. */\nexport class InvalidCredentialsError extends IdentityError {\n constructor() {\n super(\"identity/invalid-credentials\", \"Invalid email or password.\", 401);\n }\n}\n\n/** A registration was attempted for an email that already exists. */\nexport class EmailAlreadyRegisteredError extends IdentityError {\n constructor() {\n super(\n \"identity/email-already-registered\",\n \"An account with this email already exists.\",\n 409,\n );\n }\n}\n\n/** The provided access token is missing, malformed, expired, or stale. */\nexport class InvalidTokenError extends IdentityError {\n constructor(message = \"Authentication token is invalid or expired.\") {\n super(\"identity/invalid-token\", message, 401);\n }\n}\n\n/** No authenticated principal is present on the request. */\nexport class UnauthenticatedError extends IdentityError {\n constructor(message = \"Authentication is required.\") {\n super(\"identity/unauthenticated\", message, 401);\n }\n}\n\n/** The authenticated principal is not permitted to perform the action. */\nexport class ForbiddenError extends IdentityError {\n constructor(message = \"You do not have permission to perform this action.\") {\n super(\"identity/forbidden\", message, 403);\n }\n}\n\n/** The user account is disabled or locked. */\nexport class AccountUnavailableError extends IdentityError {\n constructor(message = \"This account is not available.\") {\n super(\"identity/account-unavailable\", message, 403);\n }\n}\n"],"mappings":";;;;;;;;AAQA,IAAa,gBAAb,cAAmC,MAAM;;CAEvC;;CAEA;CAEA,YAAY,MAAc,SAAiB,YAAoB;EAC7D,MAAM,OAAO;EACb,KAAK,OAAO,IAAI,OAAO;EACvB,KAAK,OAAO;EACZ,KAAK,aAAa;CACpB;AACF;;AAGA,IAAa,sBAAb,cAAyC,cAAc;CACrD,YAAY,SAAiB;EAC3B,MAAM,2BAA2B,SAAS,GAAG;CAC/C;AACF;;AAGA,IAAa,0BAAb,cAA6C,cAAc;CACzD,cAAc;EACZ,MAAM,gCAAgC,8BAA8B,GAAG;CACzE;AACF;;AAGA,IAAa,8BAAb,cAAiD,cAAc;CAC7D,cAAc;EACZ,MACE,qCACA,8CACA,GACF;CACF;AACF;;AAGA,IAAa,oBAAb,cAAuC,cAAc;CACnD,YAAY,UAAU,+CAA+C;EACnE,MAAM,0BAA0B,SAAS,GAAG;CAC9C;AACF;;AAGA,IAAa,uBAAb,cAA0C,cAAc;CACtD,YAAY,UAAU,+BAA+B;EACnD,MAAM,4BAA4B,SAAS,GAAG;CAChD;AACF;;AAGA,IAAa,iBAAb,cAAoC,cAAc;CAChD,YAAY,UAAU,sDAAsD;EAC1E,MAAM,sBAAsB,SAAS,GAAG;CAC1C;AACF;;AAGA,IAAa,0BAAb,cAA6C,cAAc;CACzD,YAAY,UAAU,kCAAkC;EACtD,MAAM,gCAAgC,SAAS,GAAG;CACpD;AACF"}