@vunexa/lixa 0.1.4 → 0.1.6-alpha.10
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 +530 -15
- package/README.template.md +288 -44
- package/dist/dao/session-cache.d.ts +2 -1
- package/dist/dao/session-cache.d.ts.map +1 -1
- package/dist/dao/state-cache.d.ts +4 -0
- package/dist/dao/state-cache.d.ts.map +1 -1
- package/dist/dao/types.d.ts +68 -75
- package/dist/dao/types.d.ts.map +1 -1
- package/dist/errors.d.ts +90 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/export-types/index.d.ts +435 -107
- package/dist/index.cjs +590 -95
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +411 -108
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +569 -94
- package/dist/index.js.map +1 -1
- package/dist/lixa.d.ts +57 -21
- package/dist/lixa.d.ts.map +1 -1
- package/dist/models/session.d.ts +17 -11
- package/dist/models/session.d.ts.map +1 -1
- package/dist/types.d.ts +39 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/cookies.d.ts +142 -0
- package/dist/utils/cookies.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -123,6 +123,41 @@ export declare enum AccountLinkingStrategy {
|
|
|
123
123
|
ISOLATED = "ISOLATED"
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Thrown when unlinking an account violates security constraints (e.g. unlinking the only login provider).
|
|
128
|
+
*
|
|
129
|
+
* @public
|
|
130
|
+
*/
|
|
131
|
+
export declare class AccountUnlinkError extends LixaError {
|
|
132
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Generates an expired session cookie payload to clear the session on logout.
|
|
137
|
+
*
|
|
138
|
+
* @param options - Optional overrides for cookie name or attributes
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```typescript
|
|
142
|
+
* const cookie = clearSessionCookie();
|
|
143
|
+
* res.setHeader("Set-Cookie", cookie.header);
|
|
144
|
+
* // or with Express:
|
|
145
|
+
* res.clearCookie(cookie.name, cookie.options);
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* @public
|
|
149
|
+
*/
|
|
150
|
+
export declare function clearSessionCookie(options?: CookieOptions): CookiePayload;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Generates an expired OAuth state cookie payload to clean up the state cookie after callback.
|
|
154
|
+
*
|
|
155
|
+
* @param options - Optional overrides for cookie attributes
|
|
156
|
+
*
|
|
157
|
+
* @public
|
|
158
|
+
*/
|
|
159
|
+
export declare function clearStateCookie(options?: CookieOptions): CookiePayload;
|
|
160
|
+
|
|
126
161
|
/**
|
|
127
162
|
* Type representing the keys of configured providers
|
|
128
163
|
*/
|
|
@@ -141,6 +176,8 @@ export declare interface ConnectedResource {
|
|
|
141
176
|
accessToken: string;
|
|
142
177
|
/** Optional refresh token for offline resource access */
|
|
143
178
|
refreshToken?: string | undefined;
|
|
179
|
+
/** Unix timestamp in milliseconds when the resource access token expires */
|
|
180
|
+
expiresAt?: number | undefined;
|
|
144
181
|
/** Resource scopes granted by the user */
|
|
145
182
|
scopes: string[];
|
|
146
183
|
/** Full raw token response from provider */
|
|
@@ -149,6 +186,91 @@ export declare interface ConnectedResource {
|
|
|
149
186
|
connectedAt: number;
|
|
150
187
|
}
|
|
151
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Sensible default cookie configuration options.
|
|
191
|
+
* Follows RFC 6265bis and OAuth 2.0 security best practices.
|
|
192
|
+
*
|
|
193
|
+
* @public
|
|
194
|
+
*/
|
|
195
|
+
export declare interface CookieOptions {
|
|
196
|
+
/**
|
|
197
|
+
* Cookie name.
|
|
198
|
+
* @default 'lixa_session'
|
|
199
|
+
*/
|
|
200
|
+
name?: string | undefined;
|
|
201
|
+
/**
|
|
202
|
+
* Cookie path.
|
|
203
|
+
* @default '/'
|
|
204
|
+
*/
|
|
205
|
+
path?: string | undefined;
|
|
206
|
+
/**
|
|
207
|
+
* Maximum age of the cookie in seconds.
|
|
208
|
+
*/
|
|
209
|
+
maxAge?: number | undefined;
|
|
210
|
+
/**
|
|
211
|
+
* Prevents client-side scripts from accessing the cookie (XSS protection).
|
|
212
|
+
* @default true
|
|
213
|
+
*/
|
|
214
|
+
httpOnly?: boolean | undefined;
|
|
215
|
+
/**
|
|
216
|
+
* Ensures the cookie is only transmitted over secure HTTPS connections.
|
|
217
|
+
* @default false in development, true in production
|
|
218
|
+
*/
|
|
219
|
+
secure?: boolean | undefined;
|
|
220
|
+
/**
|
|
221
|
+
* Controls whether the cookie is sent with cross-site requests (CSRF protection).
|
|
222
|
+
* @default 'lax'
|
|
223
|
+
*/
|
|
224
|
+
sameSite?: "lax" | "strict" | "none" | undefined;
|
|
225
|
+
/**
|
|
226
|
+
* Cookie domain.
|
|
227
|
+
*/
|
|
228
|
+
domain?: string | undefined;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Cookie payload containing name, value, options, and formatted header.
|
|
233
|
+
*
|
|
234
|
+
* @public
|
|
235
|
+
*/
|
|
236
|
+
export declare interface CookiePayload {
|
|
237
|
+
name: string;
|
|
238
|
+
value: string;
|
|
239
|
+
options: CookieOptions;
|
|
240
|
+
/**
|
|
241
|
+
* Formatted `Set-Cookie` header value string.
|
|
242
|
+
*/
|
|
243
|
+
header: string;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Generates a session cookie payload with secure default options.
|
|
248
|
+
*
|
|
249
|
+
* @param sessionId - The session identifier string
|
|
250
|
+
* @param options - Optional overrides for cookie attributes
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ```typescript
|
|
254
|
+
* const cookie = createSessionCookie(sessionId);
|
|
255
|
+
* res.setHeader("Set-Cookie", cookie.header);
|
|
256
|
+
* // or with Express:
|
|
257
|
+
* res.cookie(cookie.name, cookie.value, cookie.options);
|
|
258
|
+
* ```
|
|
259
|
+
*
|
|
260
|
+
* @public
|
|
261
|
+
*/
|
|
262
|
+
export declare function createSessionCookie(sessionId: string, options?: CookieOptions): CookiePayload;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Generates an OAuth CSRF state cookie payload for in-flight authorization flows.
|
|
266
|
+
*
|
|
267
|
+
* @param state - The random state string
|
|
268
|
+
* @param options - Optional overrides for cookie attributes
|
|
269
|
+
*
|
|
270
|
+
* @public
|
|
271
|
+
*/
|
|
272
|
+
export declare function createStateCookie(state: string, options?: CookieOptions): CookiePayload;
|
|
273
|
+
|
|
152
274
|
/**
|
|
153
275
|
* Decode JWT ID token to extract user information
|
|
154
276
|
*
|
|
@@ -156,6 +278,30 @@ export declare interface ConnectedResource {
|
|
|
156
278
|
*/
|
|
157
279
|
export declare function decodeIdToken(idToken: string): UserInfo;
|
|
158
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Default session cookie name.
|
|
283
|
+
* @public
|
|
284
|
+
*/
|
|
285
|
+
export declare const DEFAULT_SESSION_COOKIE_NAME = "lixa_session";
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Default session max age in seconds (24 hours).
|
|
289
|
+
* @public
|
|
290
|
+
*/
|
|
291
|
+
export declare const DEFAULT_SESSION_MAX_AGE_SECONDS: number;
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Default OAuth state cookie name.
|
|
295
|
+
* @public
|
|
296
|
+
*/
|
|
297
|
+
export declare const DEFAULT_STATE_COOKIE_NAME = "lixa_oauth_state";
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Default OAuth state max age in seconds (5 minutes / 300 seconds).
|
|
301
|
+
* @public
|
|
302
|
+
*/
|
|
303
|
+
export declare const DEFAULT_STATE_MAX_AGE_SECONDS: number;
|
|
304
|
+
|
|
159
305
|
/**
|
|
160
306
|
* Determine OAuth provider from ID token issuer
|
|
161
307
|
*
|
|
@@ -163,6 +309,15 @@ export declare function decodeIdToken(idToken: string): UserInfo;
|
|
|
163
309
|
*/
|
|
164
310
|
export declare function determineProviderFromIssuer(userInfo: UserInfo): string | null;
|
|
165
311
|
|
|
312
|
+
/**
|
|
313
|
+
* Thrown when account linking fails, e.g. when unverified email linking is rejected.
|
|
314
|
+
*
|
|
315
|
+
* @public
|
|
316
|
+
*/
|
|
317
|
+
export declare class EmailNotVerifiedError extends LixaError {
|
|
318
|
+
constructor(email?: string, details?: Record<string, unknown>);
|
|
319
|
+
}
|
|
320
|
+
|
|
166
321
|
/**
|
|
167
322
|
* Extract user info from OAuth token data
|
|
168
323
|
*
|
|
@@ -217,6 +372,33 @@ export declare function extractUserInfo(tokenData: OAuthTokenResponse, providerM
|
|
|
217
372
|
*/
|
|
218
373
|
export declare function fetchUserInfo(accessToken: string, userInfoEndpoint: string): Promise<UserInfo>;
|
|
219
374
|
|
|
375
|
+
/**
|
|
376
|
+
* Thrown when OAuth callback parameters (e.g. authorization code or state) are missing or malformed.
|
|
377
|
+
*
|
|
378
|
+
* @public
|
|
379
|
+
*/
|
|
380
|
+
export declare class InvalidOAuthCallbackError extends LixaError {
|
|
381
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Thrown when a provider configuration is invalid or missing required credentials.
|
|
386
|
+
*
|
|
387
|
+
* @public
|
|
388
|
+
*/
|
|
389
|
+
export declare class InvalidProviderConfigError extends LixaError {
|
|
390
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Thrown when an OAuth state parameter is invalid, missing, or has expired.
|
|
395
|
+
*
|
|
396
|
+
* @public
|
|
397
|
+
*/
|
|
398
|
+
export declare class InvalidStateError extends LixaError {
|
|
399
|
+
constructor(message?: string, details?: Record<string, unknown>);
|
|
400
|
+
}
|
|
401
|
+
|
|
220
402
|
/**
|
|
221
403
|
* Interface for OAuth 2.0 and OpenID Connect provider implementations.
|
|
222
404
|
*
|
|
@@ -357,6 +539,12 @@ export declare interface IProvider {
|
|
|
357
539
|
authScopes?: string[];
|
|
358
540
|
}
|
|
359
541
|
|
|
542
|
+
/**
|
|
543
|
+
* Checks if the runtime environment is production.
|
|
544
|
+
* @public
|
|
545
|
+
*/
|
|
546
|
+
export declare function isProductionEnvironment(): boolean;
|
|
547
|
+
|
|
360
548
|
/**
|
|
361
549
|
* Represents a linked provider account within a user's session.
|
|
362
550
|
*
|
|
@@ -432,11 +620,15 @@ declare interface LinkedAccount {
|
|
|
432
620
|
export declare class Lixa<TConfig extends LixaConfig<Record<string, ProviderConfig>> = LixaConfig> {
|
|
433
621
|
private static DEFAULT_PROVIDERS;
|
|
434
622
|
private static CONFIGURED_PROVIDERS;
|
|
435
|
-
private
|
|
436
|
-
private
|
|
623
|
+
private localStateHandler;
|
|
624
|
+
private localSessionHandler;
|
|
625
|
+
private localResourceHandler;
|
|
626
|
+
private userResourceStore;
|
|
627
|
+
private refreshMutexes;
|
|
437
628
|
private config;
|
|
438
629
|
private stateHandler;
|
|
439
630
|
private sessionHandler;
|
|
631
|
+
private resourceHandler;
|
|
440
632
|
private debug;
|
|
441
633
|
/**
|
|
442
634
|
* Creates a new Lixa instance with the provided configuration.
|
|
@@ -457,7 +649,7 @@ export declare class Lixa<TConfig extends LixaConfig<Record<string, ProviderConf
|
|
|
457
649
|
*
|
|
458
650
|
* @param name - The provider name
|
|
459
651
|
* @param config - The provider configuration
|
|
460
|
-
* @throws
|
|
652
|
+
* @throws InvalidProviderConfigError when required fields are missing or invalid
|
|
461
653
|
*/
|
|
462
654
|
private validateProviderConfig;
|
|
463
655
|
/**
|
|
@@ -465,20 +657,16 @@ export declare class Lixa<TConfig extends LixaConfig<Record<string, ProviderConf
|
|
|
465
657
|
*
|
|
466
658
|
* @param name - The provider name
|
|
467
659
|
* @param provider - The provider implementation
|
|
468
|
-
* @throws
|
|
660
|
+
* @throws InvalidProviderConfigError when required properties are missing
|
|
469
661
|
*/
|
|
470
662
|
private validateProviderImplementation;
|
|
471
663
|
/**
|
|
472
|
-
* Structured
|
|
664
|
+
* Structured logging with standardized format and custom logger support.
|
|
473
665
|
*
|
|
474
|
-
* @param level - Log level (INFO, WARN, ERROR)
|
|
475
|
-
* @param context - Context of the log (Init, Auth, Token, Session, State)
|
|
666
|
+
* @param level - Log level (INFO, WARN, ERROR, DEBUG)
|
|
667
|
+
* @param context - Context of the log (Init, Auth, Token, Session, State, AccountLinking, Resource)
|
|
476
668
|
* @param message - Log message
|
|
477
669
|
* @param data - Optional data to log
|
|
478
|
-
*
|
|
479
|
-
* @remarks
|
|
480
|
-
* Format: [Lixa] [timestamp] [level] [context] message
|
|
481
|
-
* Only logs when debug mode is enabled.
|
|
482
670
|
*/
|
|
483
671
|
private log;
|
|
484
672
|
/**
|
|
@@ -677,7 +865,7 @@ export declare class Lixa<TConfig extends LixaConfig<Record<string, ProviderConf
|
|
|
677
865
|
*/
|
|
678
866
|
getAuthUrl(provider: ConfiguredProviderKey<TConfig> | string, state?: string): Promise<string>;
|
|
679
867
|
/**
|
|
680
|
-
* Restricts primary authentication scopes strictly to AuthN identity scopes.
|
|
868
|
+
* Restricts primary authentication scopes strictly to AuthN identity scopes unless allowNonAuthScopes is true.
|
|
681
869
|
*/
|
|
682
870
|
private resolveAuthNScopes;
|
|
683
871
|
/**
|
|
@@ -743,11 +931,9 @@ export declare class Lixa<TConfig extends LixaConfig<Record<string, ProviderConf
|
|
|
743
931
|
prompt?: string;
|
|
744
932
|
extraConfig?: Record<string, string>;
|
|
745
933
|
}): Promise<string>;
|
|
934
|
+
private getUserKeyFromSession;
|
|
746
935
|
/**
|
|
747
|
-
* Handles the OAuth callback for a connected resource provider and stores resource tokens
|
|
748
|
-
*
|
|
749
|
-
* @param params - Object containing sessionId, provider, code, state, and requested scopes
|
|
750
|
-
* @returns Updated Session containing stored resource tokens under session.resources[provider]
|
|
936
|
+
* Handles the OAuth callback for a connected resource provider and stores resource tokens bound to user account.
|
|
751
937
|
*/
|
|
752
938
|
handleResourceCallback(params: {
|
|
753
939
|
sessionId: string;
|
|
@@ -757,20 +943,58 @@ export declare class Lixa<TConfig extends LixaConfig<Record<string, ProviderConf
|
|
|
757
943
|
scopes?: string[];
|
|
758
944
|
}): Promise<Session>;
|
|
759
945
|
/**
|
|
760
|
-
* Retrieves a connected resource
|
|
946
|
+
* Retrieves a connected resource for a specific User ID / Email directly (independent of session IDs).
|
|
947
|
+
* Automatically refreshes expired access tokens if a refresh token is present.
|
|
948
|
+
*
|
|
949
|
+
* @param userIdOrEmail - User identifier or email
|
|
950
|
+
* @param provider - Resource provider identifier (e.g. 'github', 'google')
|
|
951
|
+
*/
|
|
952
|
+
getUserResource(userIdOrEmail: string, provider: string): Promise<ConnectedResource | null>;
|
|
953
|
+
/**
|
|
954
|
+
* Retrieves all connected resources for a specific User ID / Email.
|
|
955
|
+
*/
|
|
956
|
+
getUserResources(userIdOrEmail: string): Promise<Record<string, ConnectedResource>>;
|
|
957
|
+
/**
|
|
958
|
+
* Retrieves a connected resource provider token for an active session, auto-refreshing expired tokens if possible.
|
|
761
959
|
*
|
|
762
960
|
* @param sessionId - Active session ID
|
|
763
|
-
* @param provider - Provider identifier (e.g. 'github')
|
|
961
|
+
* @param provider - Provider identifier (e.g. 'github', 'google')
|
|
764
962
|
*/
|
|
765
963
|
getConnectedResource(sessionId: string, provider: string): Promise<ConnectedResource | null>;
|
|
766
964
|
/**
|
|
767
|
-
*
|
|
965
|
+
* Refreshes a user's resource access token using its refresh token.
|
|
966
|
+
* Deduplicates concurrent refresh requests via an in-flight promise mutex.
|
|
768
967
|
*
|
|
769
|
-
* @param
|
|
770
|
-
* @param provider - Provider identifier
|
|
968
|
+
* @param userIdOrEmail - User identifier or email
|
|
969
|
+
* @param provider - Provider identifier (e.g. 'google', 'github')
|
|
970
|
+
*/
|
|
971
|
+
refreshUserResourceToken(userIdOrEmail: string, provider: string, existingResource?: ConnectedResource): Promise<ConnectedResource>;
|
|
972
|
+
/**
|
|
973
|
+
* Internal execution of refresh token exchange.
|
|
974
|
+
*/
|
|
975
|
+
private executeRefreshUserResourceToken;
|
|
976
|
+
/**
|
|
977
|
+
* Refreshes a connected resource access token for an active session.
|
|
978
|
+
*/
|
|
979
|
+
refreshResourceToken(sessionId: string, provider: string): Promise<ConnectedResource>;
|
|
980
|
+
/**
|
|
981
|
+
* Disconnects a resource provider for a specific User ID / Email.
|
|
982
|
+
*/
|
|
983
|
+
disconnectUserResource(userIdOrEmail: string, provider: string): Promise<boolean>;
|
|
984
|
+
/**
|
|
985
|
+
* Disconnects a resource provider from an active session and user account.
|
|
771
986
|
*/
|
|
772
987
|
disconnectResource(sessionId: string, provider: string): Promise<boolean>;
|
|
988
|
+
/**
|
|
989
|
+
* Retrieves active session details from session storage.
|
|
990
|
+
*/
|
|
773
991
|
fetchSessionInfo(sessionId: string): Promise<Session | null>;
|
|
992
|
+
/**
|
|
993
|
+
* Deletes a session from session storage (e.g. on logout).
|
|
994
|
+
*
|
|
995
|
+
* @param sessionId - Active session identifier
|
|
996
|
+
*/
|
|
997
|
+
deleteSession(sessionId: string): Promise<void>;
|
|
774
998
|
private exchangeCodeForToken;
|
|
775
999
|
private findProviderByType;
|
|
776
1000
|
}
|
|
@@ -815,14 +1039,64 @@ export declare interface LixaConfig<TProviders extends Record<string, ProviderCo
|
|
|
815
1039
|
* @see {@link SessionHandler}
|
|
816
1040
|
*/
|
|
817
1041
|
sessionHandler?: SessionHandler;
|
|
1042
|
+
/**
|
|
1043
|
+
* Optional custom resource handler.
|
|
1044
|
+
* Handles storage and management of long-lived third-party resource provider tokens (AuthZ)
|
|
1045
|
+
* bound directly to user accounts (User ID or Email), independent of transient session IDs.
|
|
1046
|
+
*
|
|
1047
|
+
* @see {@link ResourceHandler}
|
|
1048
|
+
*/
|
|
1049
|
+
resourceHandler?: ResourceHandler;
|
|
818
1050
|
/**
|
|
819
1051
|
* Enable debug logging.
|
|
820
1052
|
* When enabled, outputs structured logs for initialization, auth flow, and errors.
|
|
821
1053
|
* Format: [Lixa] [timestamp] [level] [context] message
|
|
822
1054
|
*/
|
|
823
1055
|
debug?: boolean;
|
|
1056
|
+
/**
|
|
1057
|
+
* Optional custom structured logger implementation.
|
|
1058
|
+
* If provided, all Lixa logs will be routed through this logger.
|
|
1059
|
+
*/
|
|
1060
|
+
logger?: LixaLogger;
|
|
824
1061
|
}
|
|
825
1062
|
|
|
1063
|
+
/**
|
|
1064
|
+
* Base error class for all Lixa authentication and authorization errors.
|
|
1065
|
+
*
|
|
1066
|
+
* @public
|
|
1067
|
+
*/
|
|
1068
|
+
export declare class LixaError extends Error {
|
|
1069
|
+
/**
|
|
1070
|
+
* Standard error code string.
|
|
1071
|
+
*/
|
|
1072
|
+
readonly code: string;
|
|
1073
|
+
/**
|
|
1074
|
+
* Additional error context data.
|
|
1075
|
+
*/
|
|
1076
|
+
readonly details: Record<string, unknown> | undefined;
|
|
1077
|
+
constructor(message: string, code?: string, details?: Record<string, unknown>);
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
/**
|
|
1081
|
+
* Custom logger interface for Lixa.
|
|
1082
|
+
* @public
|
|
1083
|
+
*/
|
|
1084
|
+
export declare interface LixaLogger {
|
|
1085
|
+
log(level: LogLevel, context: LogContext, message: string, data?: Record<string, unknown>): void;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
/**
|
|
1089
|
+
* Log context for Lixa structured logging.
|
|
1090
|
+
* @public
|
|
1091
|
+
*/
|
|
1092
|
+
export declare type LogContext = "Init" | "Auth" | "Token" | "Session" | "State" | "AccountLinking" | "Resource";
|
|
1093
|
+
|
|
1094
|
+
/**
|
|
1095
|
+
* Log level for Lixa structured logging.
|
|
1096
|
+
* @public
|
|
1097
|
+
*/
|
|
1098
|
+
export declare type LogLevel = "INFO" | "WARN" | "ERROR" | "DEBUG";
|
|
1099
|
+
|
|
826
1100
|
/**
|
|
827
1101
|
* OAuth 2.0 token response structure.
|
|
828
1102
|
* Based on RFC 6749 Section 5.1 and OpenID Connect Core 1.0 Section 3.1.3.3
|
|
@@ -917,6 +1191,12 @@ export declare type ProviderConfig = {
|
|
|
917
1191
|
redirectUri: string;
|
|
918
1192
|
/** Array of OAuth scopes to request */
|
|
919
1193
|
scopes: string[];
|
|
1194
|
+
/**
|
|
1195
|
+
* Set to true to allow non-identity (resource) scopes during primary authentication flow.
|
|
1196
|
+
* By default (false), Lixa restricts primary AuthN scopes to identity scopes to maintain
|
|
1197
|
+
* clean AuthN vs AuthZ separation.
|
|
1198
|
+
*/
|
|
1199
|
+
allowNonAuthScopes?: boolean;
|
|
920
1200
|
/** Additional provider-specific configuration parameters */
|
|
921
1201
|
extraConfig?: Record<string, string>;
|
|
922
1202
|
} & ({
|
|
@@ -945,6 +1225,73 @@ export declare interface ProviderMetadata {
|
|
|
945
1225
|
};
|
|
946
1226
|
}
|
|
947
1227
|
|
|
1228
|
+
/**
|
|
1229
|
+
* Thrown when attempting to use a provider that is not configured in the Lixa instance.
|
|
1230
|
+
*
|
|
1231
|
+
* @public
|
|
1232
|
+
*/
|
|
1233
|
+
export declare class ProviderNotConfiguredError extends LixaError {
|
|
1234
|
+
constructor(provider: string, details?: Record<string, unknown>);
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* Thrown when a refresh token is missing or token refresh fails for a connected resource.
|
|
1239
|
+
*
|
|
1240
|
+
* @public
|
|
1241
|
+
*/
|
|
1242
|
+
export declare class RefreshTokenError extends LixaError {
|
|
1243
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
/**
|
|
1247
|
+
* Resource handler configuration.
|
|
1248
|
+
*
|
|
1249
|
+
* @public
|
|
1250
|
+
*/
|
|
1251
|
+
export declare interface ResourceHandler {
|
|
1252
|
+
resourceStorage?: ResourceStorage;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
/**
|
|
1256
|
+
* Resource storage operations interface.
|
|
1257
|
+
*
|
|
1258
|
+
* @remarks
|
|
1259
|
+
* Manages long-lived third-party resource provider tokens (AuthZ) bound to a user account
|
|
1260
|
+
* (User ID or Email), independent of short-lived user sessions.
|
|
1261
|
+
*
|
|
1262
|
+
* @public
|
|
1263
|
+
*/
|
|
1264
|
+
export declare interface ResourceStorage {
|
|
1265
|
+
/**
|
|
1266
|
+
* Saves a connected resource token for a user.
|
|
1267
|
+
*
|
|
1268
|
+
* @param userId - Unique user identifier or email
|
|
1269
|
+
* @param provider - Resource provider name (e.g. 'github', 'google')
|
|
1270
|
+
* @param resource - Connected resource details including access & refresh tokens
|
|
1271
|
+
*/
|
|
1272
|
+
saveResource(userId: string, provider: string, resource: ConnectedResource): Promise<void>;
|
|
1273
|
+
/**
|
|
1274
|
+
* Retrieves a connected resource token for a user.
|
|
1275
|
+
*
|
|
1276
|
+
* @param userId - Unique user identifier or email
|
|
1277
|
+
* @param provider - Resource provider name
|
|
1278
|
+
*/
|
|
1279
|
+
getResource(userId: string, provider: string): Promise<ConnectedResource | null>;
|
|
1280
|
+
/**
|
|
1281
|
+
* Retrieves all connected resources for a user.
|
|
1282
|
+
*
|
|
1283
|
+
* @param userId - Unique user identifier or email
|
|
1284
|
+
*/
|
|
1285
|
+
getUserResources(userId: string): Promise<Record<string, ConnectedResource>>;
|
|
1286
|
+
/**
|
|
1287
|
+
* Deletes a connected resource token for a user.
|
|
1288
|
+
*
|
|
1289
|
+
* @param userId - Unique user identifier or email
|
|
1290
|
+
* @param provider - Resource provider name
|
|
1291
|
+
*/
|
|
1292
|
+
deleteResource(userId: string, provider: string): Promise<void>;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
948
1295
|
/**
|
|
949
1296
|
* Helper type to create a configuration with only registered providers.
|
|
950
1297
|
* Use this with Lixa.createConfig() for type safety.
|
|
@@ -958,6 +1305,18 @@ export declare type SafeLixaConfig<TProviders extends Record<string, ProviderCon
|
|
|
958
1305
|
providers: TProviders;
|
|
959
1306
|
};
|
|
960
1307
|
|
|
1308
|
+
/**
|
|
1309
|
+
* Serializes a cookie name, value, and options into a standard `Set-Cookie` header string.
|
|
1310
|
+
*
|
|
1311
|
+
* @param name - Cookie name
|
|
1312
|
+
* @param value - Cookie value
|
|
1313
|
+
* @param options - Cookie attributes
|
|
1314
|
+
* @returns Formatted `Set-Cookie` string
|
|
1315
|
+
*
|
|
1316
|
+
* @public
|
|
1317
|
+
*/
|
|
1318
|
+
export declare function serializeCookie(name: string, value: string, options?: CookieOptions): string;
|
|
1319
|
+
|
|
961
1320
|
/**
|
|
962
1321
|
* Represents a user session after successful OAuth authentication.
|
|
963
1322
|
*
|
|
@@ -976,25 +1335,29 @@ export declare interface Session<TRaw = OAuthTokenResponse> {
|
|
|
976
1335
|
*/
|
|
977
1336
|
id?: string;
|
|
978
1337
|
/**
|
|
979
|
-
*
|
|
1338
|
+
* Linked identity provider accounts (AuthN) keyed by provider name.
|
|
1339
|
+
* Single source of truth for all authenticated user SSO identities.
|
|
980
1340
|
*/
|
|
981
|
-
|
|
1341
|
+
accounts?: Record<string, LinkedAccount>;
|
|
1342
|
+
/**
|
|
1343
|
+
* Connected third-party resource provider tokens (AuthZ) keyed by provider name.
|
|
1344
|
+
* Single source of truth for all post-login third-party API permissions.
|
|
1345
|
+
*/
|
|
1346
|
+
resources?: Record<string, ConnectedResource>;
|
|
982
1347
|
/** Unique unified user ID across linked accounts */
|
|
983
1348
|
userId?: string;
|
|
984
1349
|
/** Primary user email */
|
|
985
1350
|
email?: string;
|
|
986
|
-
/**
|
|
1351
|
+
/**
|
|
1352
|
+
* Optional primary access token or custom session token identifier.
|
|
1353
|
+
*/
|
|
1354
|
+
token?: string;
|
|
1355
|
+
/** Optional current active auth provider for this session turn */
|
|
987
1356
|
provider?: string;
|
|
988
|
-
/** Linked SSO provider accounts keyed by provider name */
|
|
989
|
-
accounts?: Record<string, LinkedAccount>;
|
|
990
|
-
/** Connected third-party resource provider tokens keyed by provider name */
|
|
991
|
-
resources?: Record<string, ConnectedResource>;
|
|
992
1357
|
/**
|
|
993
|
-
*
|
|
994
|
-
* Contains the complete OAuth token response and any additional data
|
|
995
|
-
* your SessionStrategy adds (user info, database IDs, etc.).
|
|
1358
|
+
* Optional raw session token response data from provider.
|
|
996
1359
|
*/
|
|
997
|
-
raw
|
|
1360
|
+
raw?: TRaw;
|
|
998
1361
|
}
|
|
999
1362
|
|
|
1000
1363
|
/**
|
|
@@ -1003,13 +1366,13 @@ export declare interface Session<TRaw = OAuthTokenResponse> {
|
|
|
1003
1366
|
* @remarks
|
|
1004
1367
|
* The SessionHandler manages session generation and storage after successful OAuth authentication.
|
|
1005
1368
|
*
|
|
1006
|
-
* -
|
|
1369
|
+
* - generateSession: Optional. Customizes how OAuth tokens are converted into session data.
|
|
1007
1370
|
* If not provided, uses default implementation (access token as session token).
|
|
1008
1371
|
*
|
|
1009
|
-
* -
|
|
1372
|
+
* - sessionStorage: Optional. Provides custom session storage (save/get/delete operations).
|
|
1010
1373
|
* If not provided, uses in-memory cache (not suitable for production).
|
|
1011
1374
|
*
|
|
1012
|
-
* For production, implement both
|
|
1375
|
+
* For production, implement both generateSession (for user creation/lookup) and sessionStorage
|
|
1013
1376
|
* (for persistent session storage with Redis, database, etc.).
|
|
1014
1377
|
*
|
|
1015
1378
|
* @example
|
|
@@ -1018,7 +1381,7 @@ export declare interface Session<TRaw = OAuthTokenResponse> {
|
|
|
1018
1381
|
* import { SessionHandler, Session, OAuthTokenResponse, ProviderMetadata, extractUserInfo } from '@vunexa/lixa';
|
|
1019
1382
|
*
|
|
1020
1383
|
* const sessionHandler: SessionHandler = {
|
|
1021
|
-
*
|
|
1384
|
+
* generateSession: async (tokenData, providerMetadata) => {
|
|
1022
1385
|
* // Extract user info and create/retrieve user
|
|
1023
1386
|
* const { userInfo } = await extractUserInfo(tokenData, providerMetadata);
|
|
1024
1387
|
* const user = await db.users.upsert({
|
|
@@ -1037,7 +1400,7 @@ export declare interface Session<TRaw = OAuthTokenResponse> {
|
|
|
1037
1400
|
* };
|
|
1038
1401
|
* },
|
|
1039
1402
|
*
|
|
1040
|
-
*
|
|
1403
|
+
* sessionStorage: {
|
|
1041
1404
|
* saveSession: async (sessionId, session, expiresInSeconds) => {
|
|
1042
1405
|
* const expiresAt = new Date(Date.now() + expiresInSeconds * 1000);
|
|
1043
1406
|
* await db.sessions.create({
|
|
@@ -1063,78 +1426,21 @@ export declare interface Session<TRaw = OAuthTokenResponse> {
|
|
|
1063
1426
|
* };
|
|
1064
1427
|
* ```
|
|
1065
1428
|
*
|
|
1066
|
-
* @example
|
|
1067
|
-
* Minimal implementation (uses defaults):
|
|
1068
|
-
* ```typescript
|
|
1069
|
-
* const sessionHandler: SessionHandler = {
|
|
1070
|
-
* storage: {
|
|
1071
|
-
* saveSession: async (sessionId, session, expiresInSeconds) => {
|
|
1072
|
-
* await redis.setex(sessionId, expiresInSeconds, JSON.stringify(session));
|
|
1073
|
-
* },
|
|
1074
|
-
* getSession: async (sessionId) => {
|
|
1075
|
-
* const data = await redis.get(sessionId);
|
|
1076
|
-
* return data ? JSON.parse(data) : null;
|
|
1077
|
-
* },
|
|
1078
|
-
* deleteSession: async (sessionId) => {
|
|
1079
|
-
* await redis.del(sessionId);
|
|
1080
|
-
* }
|
|
1081
|
-
* }
|
|
1082
|
-
* };
|
|
1083
|
-
* ```
|
|
1084
|
-
*
|
|
1085
1429
|
* @public
|
|
1086
1430
|
*/
|
|
1087
1431
|
export declare interface SessionHandler {
|
|
1088
1432
|
/**
|
|
1089
|
-
* Generates session data from OAuth token data.
|
|
1433
|
+
* Generates session data from OAuth token data (camelCase).
|
|
1090
1434
|
*
|
|
1091
1435
|
* @param tokenData - The token data received from the OAuth provider's token endpoint
|
|
1092
1436
|
* @param providerMetadata - Provider metadata including name and endpoints
|
|
1093
1437
|
* @returns A Promise that resolves to session data
|
|
1094
|
-
*
|
|
1095
|
-
* @remarks
|
|
1096
|
-
* This method is responsible for creating session data from OAuth tokens.
|
|
1097
|
-
* It is called after successfully exchanging the authorization code for tokens.
|
|
1098
|
-
*
|
|
1099
|
-
* Token Data:
|
|
1100
|
-
* - access_token: OAuth access token
|
|
1101
|
-
* - refresh_token: OAuth refresh token (optional)
|
|
1102
|
-
* - expires_in: Token expiration time in seconds
|
|
1103
|
-
* - token_type: Token type (usually "Bearer")
|
|
1104
|
-
* - id_token: OpenID Connect ID token (for OIDC providers)
|
|
1105
|
-
* - scope: Granted scopes
|
|
1106
|
-
*
|
|
1107
|
-
* Provider Metadata:
|
|
1108
|
-
* - name: The provider name (e.g., 'google', 'github')
|
|
1109
|
-
* - endpoints: Provider endpoints (authorization, token, userInfo)
|
|
1110
|
-
*
|
|
1111
|
-
* Your implementation should:
|
|
1112
|
-
* 1. Extract user info (using extractUserInfo or decode ID token)
|
|
1113
|
-
* 2. Create or lookup users in your database
|
|
1114
|
-
* 3. Build and return session data with any custom fields
|
|
1115
|
-
*
|
|
1116
|
-
* Note: This method should NOT store the session. Storage is handled by the storage object.
|
|
1117
|
-
*
|
|
1118
|
-
* If not provided, defaults to using the access token as the session token.
|
|
1119
|
-
*
|
|
1120
|
-
* @example
|
|
1121
|
-
* ```typescript
|
|
1122
|
-
* GenerateSession: async (tokenData, providerMetadata) => {
|
|
1123
|
-
* const { userInfo } = await extractUserInfo(tokenData, providerMetadata);
|
|
1124
|
-
* const user = await db.users.upsert({ email: userInfo.email });
|
|
1125
|
-
*
|
|
1126
|
-
* return {
|
|
1127
|
-
* token: tokenData.access_token,
|
|
1128
|
-
* raw: {
|
|
1129
|
-
* ...tokenData,
|
|
1130
|
-
* userId: user.id,
|
|
1131
|
-
* provider: providerMetadata.name
|
|
1132
|
-
* }
|
|
1133
|
-
* };
|
|
1134
|
-
* }
|
|
1135
|
-
* ```
|
|
1136
1438
|
*/
|
|
1137
1439
|
generateSession?<T extends Session>(tokenData: OAuthTokenResponse, providerMetadata: ProviderMetadata): Promise<T>;
|
|
1440
|
+
/**
|
|
1441
|
+
* Generates session data from OAuth token data (PascalCase alias for backward compatibility).
|
|
1442
|
+
*/
|
|
1443
|
+
GenerateSession?<T extends Session>(tokenData: OAuthTokenResponse, providerMetadata: ProviderMetadata): Promise<T>;
|
|
1138
1444
|
/**
|
|
1139
1445
|
* Session storage operations.
|
|
1140
1446
|
*
|
|
@@ -1145,13 +1451,15 @@ export declare interface SessionHandler {
|
|
|
1145
1451
|
* If not provided, uses in-memory cache (not suitable for production).
|
|
1146
1452
|
*/
|
|
1147
1453
|
sessionStorage?: SessionStorage;
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
/**
|
|
1457
|
+
* Thrown when a user session is not found or has expired.
|
|
1458
|
+
*
|
|
1459
|
+
* @public
|
|
1460
|
+
*/
|
|
1461
|
+
export declare class SessionNotFoundError extends LixaError {
|
|
1462
|
+
constructor(message?: string, details?: Record<string, unknown>);
|
|
1155
1463
|
}
|
|
1156
1464
|
|
|
1157
1465
|
/**
|
|
@@ -1168,7 +1476,7 @@ export declare interface SessionStorage {
|
|
|
1168
1476
|
* Saves a session with expiration.
|
|
1169
1477
|
*
|
|
1170
1478
|
* @param sessionId - Unique session identifier
|
|
1171
|
-
* @param session - Session data from
|
|
1479
|
+
* @param session - Session data from generateSession()
|
|
1172
1480
|
* @param expiresInSeconds - TTL in seconds (typically 86400 for 24 hours)
|
|
1173
1481
|
*/
|
|
1174
1482
|
saveSession<T extends Session>(sessionId: string, session: T, expiresInSeconds: number): Promise<void>;
|
|
@@ -1330,10 +1638,20 @@ export declare interface StateHandler {
|
|
|
1330
1638
|
* }
|
|
1331
1639
|
* ```
|
|
1332
1640
|
*/
|
|
1641
|
+
/**
|
|
1642
|
+
* Generates OAuth state parameter and associated data (camelCase).
|
|
1643
|
+
*/
|
|
1333
1644
|
generateState?(provider: string): Promise<{
|
|
1334
1645
|
state: string;
|
|
1335
1646
|
data: StateData;
|
|
1336
1647
|
}>;
|
|
1648
|
+
/**
|
|
1649
|
+
* Generates OAuth state parameter and associated data (PascalCase alias for backward compatibility).
|
|
1650
|
+
*/
|
|
1651
|
+
GenerateState?(provider: string): Promise<{
|
|
1652
|
+
state: string;
|
|
1653
|
+
data: StateData;
|
|
1654
|
+
}>;
|
|
1337
1655
|
/**
|
|
1338
1656
|
* State storage operations.
|
|
1339
1657
|
*
|
|
@@ -1379,6 +1697,16 @@ export declare interface StateStorage {
|
|
|
1379
1697
|
deleteState(state: string): Promise<void>;
|
|
1380
1698
|
}
|
|
1381
1699
|
|
|
1700
|
+
/**
|
|
1701
|
+
* Thrown when exchanging an authorization code for OAuth tokens fails at the provider endpoint.
|
|
1702
|
+
*
|
|
1703
|
+
* @public
|
|
1704
|
+
*/
|
|
1705
|
+
export declare class TokenExchangeError extends LixaError {
|
|
1706
|
+
readonly status: number | undefined;
|
|
1707
|
+
constructor(message: string, status?: number, details?: Record<string, unknown>);
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1382
1710
|
/**
|
|
1383
1711
|
* User information extracted from OAuth provider
|
|
1384
1712
|
*
|