@vunexa/lixa 0.0.1-alpha.19 → 0.0.1-alpha.21
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 +717 -29
- package/dist/dao/types.d.ts +239 -5
- package/dist/dao/types.d.ts.map +1 -1
- package/dist/export-types/index.d.ts +785 -43
- package/dist/index.cjs +277 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +787 -40
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +277 -41
- package/dist/index.js.map +1 -1
- package/dist/lixa.d.ts +185 -16
- package/dist/lixa.d.ts.map +1 -1
- package/dist/models/session.d.ts +107 -4
- package/dist/models/session.d.ts.map +1 -1
- package/dist/providers/IProvider.d.ts +121 -4
- package/dist/providers/IProvider.d.ts.map +1 -1
- package/dist/providers/index.d.ts +0 -2
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/types.d.ts +129 -14
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -16
- package/dist/IProvider-2tDwRAnH.d.cts +0 -18
- package/dist/IProvider-2tDwRAnH.d.ts +0 -18
- package/dist/export-types/providers.d.ts +0 -61
- package/dist/providers/github.d.ts +0 -13
- package/dist/providers/github.d.ts.map +0 -1
- package/dist/providers/google.d.ts +0 -13
- package/dist/providers/google.d.ts.map +0 -1
- package/dist/providers-entry.cjs +0 -48
- package/dist/providers-entry.cjs.map +0 -1
- package/dist/providers-entry.d.cts +0 -25
- package/dist/providers-entry.d.ts +0 -22
- package/dist/providers-entry.d.ts.map +0 -1
- package/dist/providers-entry.js +0 -20
- package/dist/providers-entry.js.map +0 -1
package/dist/lixa.d.ts
CHANGED
|
@@ -10,18 +10,18 @@ type ConfiguredProviderKey<T extends LixaConfig<any>> = keyof T['providers'];
|
|
|
10
10
|
*
|
|
11
11
|
* @remarks
|
|
12
12
|
* Lixa simplifies multi-provider authentication flows and supports extensible session management.
|
|
13
|
+
* Providers can be passed inline in the configuration, eliminating the need for pre-registration.
|
|
13
14
|
*
|
|
14
15
|
* @example
|
|
16
|
+
* Using built-in providers from @vunexa/lixa-providers:
|
|
15
17
|
* ```typescript
|
|
16
18
|
* import { Lixa } from '@vunexa/lixa';
|
|
17
|
-
* import { GoogleProvider } from '@vunexa/lixa
|
|
19
|
+
* import { GoogleProvider } from '@vunexa/lixa-providers';
|
|
18
20
|
*
|
|
19
|
-
*
|
|
20
|
-
* Lixa.registerProvider({ google: new GoogleProvider() });
|
|
21
|
-
*
|
|
22
|
-
* const config = Lixa.createConfig({
|
|
21
|
+
* const lixa = new Lixa({
|
|
23
22
|
* providers: {
|
|
24
23
|
* google: {
|
|
24
|
+
* provider: new GoogleProvider(),
|
|
25
25
|
* clientId: 'your-client-id',
|
|
26
26
|
* clientSecret: 'your-client-secret',
|
|
27
27
|
* redirectUri: 'https://yourapp.com/auth/google/callback',
|
|
@@ -29,13 +29,36 @@ type ConfiguredProviderKey<T extends LixaConfig<any>> = keyof T['providers'];
|
|
|
29
29
|
* }
|
|
30
30
|
* }
|
|
31
31
|
* });
|
|
32
|
+
* ```
|
|
32
33
|
*
|
|
33
|
-
*
|
|
34
|
+
* @example
|
|
35
|
+
* Using custom inline providers:
|
|
36
|
+
* ```typescript
|
|
37
|
+
* import { Lixa, IProvider } from '@vunexa/lixa';
|
|
38
|
+
*
|
|
39
|
+
* const customProvider: IProvider = {
|
|
40
|
+
* authorizationEndpoint: 'https://custom.com/oauth/authorize',
|
|
41
|
+
* tokenEndpoint: 'https://custom.com/oauth/token',
|
|
42
|
+
* userInfoEndpoint: 'https://custom.com/api/user'
|
|
43
|
+
* };
|
|
44
|
+
*
|
|
45
|
+
* const lixa = new Lixa({
|
|
46
|
+
* providers: {
|
|
47
|
+
* custom: {
|
|
48
|
+
* provider: customProvider,
|
|
49
|
+
* clientId: 'your-client-id',
|
|
50
|
+
* clientSecret: 'your-client-secret',
|
|
51
|
+
* redirectUri: 'https://yourapp.com/auth/custom/callback',
|
|
52
|
+
* scopes: ['read:user']
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
* });
|
|
34
56
|
* ```
|
|
35
57
|
*
|
|
36
58
|
* @public
|
|
37
59
|
*/
|
|
38
60
|
declare class Lixa<TConfig extends LixaConfig<any> = LixaConfig> {
|
|
61
|
+
private static DEFAULT_PROVIDERS;
|
|
39
62
|
private static CONFIGURED_PROVIDERS;
|
|
40
63
|
private static LOCAL_STATE_CACHE;
|
|
41
64
|
private static LOCAL_SESSION_CACHE;
|
|
@@ -48,17 +71,52 @@ declare class Lixa<TConfig extends LixaConfig<any> = LixaConfig> {
|
|
|
48
71
|
/**
|
|
49
72
|
* Creates a new Lixa instance with the provided configuration.
|
|
50
73
|
*
|
|
74
|
+
* @remarks
|
|
75
|
+
* Providers can be passed inline in the configuration using the `provider` field.
|
|
76
|
+
* Provider resolution priority: inline custom provider > default providers > legacy registry.
|
|
77
|
+
*
|
|
51
78
|
* @param config - The configuration object containing provider settings and optional session strategy
|
|
79
|
+
*
|
|
80
|
+
* @throws Error when provider configuration is missing required fields
|
|
81
|
+
* @throws Error when provider implementation is missing required properties
|
|
82
|
+
* @throws Error when provider is not available and no inline implementation is provided
|
|
52
83
|
*/
|
|
53
84
|
constructor(config: TConfig);
|
|
85
|
+
/**
|
|
86
|
+
* Validates that a provider configuration has all required credentials.
|
|
87
|
+
*
|
|
88
|
+
* @param name - The provider name
|
|
89
|
+
* @param config - The provider configuration
|
|
90
|
+
* @throws Error when required fields are missing or invalid
|
|
91
|
+
*/
|
|
92
|
+
private validateProviderConfig;
|
|
93
|
+
/**
|
|
94
|
+
* Validates that a provider implementation has all required properties.
|
|
95
|
+
*
|
|
96
|
+
* @param name - The provider name
|
|
97
|
+
* @param provider - The provider implementation
|
|
98
|
+
* @throws Error when required properties are missing
|
|
99
|
+
*/
|
|
100
|
+
private validateProviderImplementation;
|
|
101
|
+
/**
|
|
102
|
+
* Structured debug logging with standardized format.
|
|
103
|
+
*
|
|
104
|
+
* @param level - Log level (INFO, WARN, ERROR)
|
|
105
|
+
* @param context - Context of the log (Init, Auth, Token, Session, State)
|
|
106
|
+
* @param message - Log message
|
|
107
|
+
* @param data - Optional data to log
|
|
108
|
+
*
|
|
109
|
+
* @remarks
|
|
110
|
+
* Format: [Lixa] [timestamp] [level] [context] message
|
|
111
|
+
* Only logs when debug mode is enabled.
|
|
112
|
+
*/
|
|
54
113
|
private log;
|
|
55
|
-
private logError;
|
|
56
114
|
/**
|
|
57
|
-
* Checks if a provider is
|
|
115
|
+
* Checks if a provider is configured for this instance.
|
|
58
116
|
* This is a type guard that narrows the provider type for use with getAuthUrl.
|
|
59
117
|
*
|
|
60
118
|
* @param provider - The provider name to check (case-insensitive)
|
|
61
|
-
* @returns True if the provider is
|
|
119
|
+
* @returns True if the provider is configured, false otherwise
|
|
62
120
|
*
|
|
63
121
|
* @example
|
|
64
122
|
* ```typescript
|
|
@@ -69,12 +127,37 @@ declare class Lixa<TConfig extends LixaConfig<any> = LixaConfig> {
|
|
|
69
127
|
* ```
|
|
70
128
|
*/
|
|
71
129
|
isProviderConfigured<T extends string>(provider: T): provider is T & ConfiguredProviderKey<TConfig>;
|
|
130
|
+
/**
|
|
131
|
+
* Gets a provider implementation by name.
|
|
132
|
+
* Resolution priority: inline custom provider > default providers > legacy registry
|
|
133
|
+
*
|
|
134
|
+
* @param name - The provider name (case-insensitive)
|
|
135
|
+
* @param config - The provider configuration
|
|
136
|
+
* @returns The provider implementation
|
|
137
|
+
* @throws Error when provider is not found
|
|
138
|
+
*/
|
|
139
|
+
private getProvider;
|
|
72
140
|
/**
|
|
73
141
|
* Registers custom OAuth providers for use with Lixa.
|
|
74
142
|
*
|
|
143
|
+
* @deprecated This method is maintained for backward compatibility.
|
|
144
|
+
* The recommended approach is to pass providers inline in the configuration:
|
|
145
|
+
* ```typescript
|
|
146
|
+
* const lixa = new Lixa({
|
|
147
|
+
* providers: {
|
|
148
|
+
* custom: {
|
|
149
|
+
* provider: new CustomProvider(),
|
|
150
|
+
* clientId: '...',
|
|
151
|
+
* // ...
|
|
152
|
+
* }
|
|
153
|
+
* }
|
|
154
|
+
* });
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
75
157
|
* @param providerMap - A map of provider names to IProvider implementations
|
|
76
158
|
*
|
|
77
159
|
* @example
|
|
160
|
+
* Legacy usage (still supported):
|
|
78
161
|
* ```typescript
|
|
79
162
|
* class CustomProvider implements IProvider {
|
|
80
163
|
* authorizationEndpoint = 'https://custom.com/oauth/authorize';
|
|
@@ -93,14 +176,31 @@ declare class Lixa<TConfig extends LixaConfig<any> = LixaConfig> {
|
|
|
93
176
|
*/
|
|
94
177
|
static getRegisteredProviders(): string[];
|
|
95
178
|
/**
|
|
96
|
-
* Creates a type-safe configuration
|
|
179
|
+
* Creates a type-safe configuration.
|
|
180
|
+
*
|
|
181
|
+
* @deprecated This method is maintained for backward compatibility.
|
|
182
|
+
* You can now pass configuration directly to the Lixa constructor without this helper.
|
|
183
|
+
*
|
|
184
|
+
* @param config - Configuration object with provider settings
|
|
185
|
+
* @returns The same configuration object with type safety
|
|
97
186
|
*
|
|
98
|
-
* @
|
|
99
|
-
*
|
|
187
|
+
* @example
|
|
188
|
+
* New approach (recommended):
|
|
189
|
+
* ```typescript
|
|
190
|
+
* const lixa = new Lixa({
|
|
191
|
+
* providers: {
|
|
192
|
+
* google: {
|
|
193
|
+
* provider: new GoogleProvider(),
|
|
194
|
+
* clientId: '...',
|
|
195
|
+
* // ...
|
|
196
|
+
* }
|
|
197
|
+
* }
|
|
198
|
+
* });
|
|
199
|
+
* ```
|
|
100
200
|
*/
|
|
101
|
-
static createConfig<T extends Record<string, ProviderConfig>>(config: LixaConfig<
|
|
201
|
+
static createConfig<T extends Record<string, ProviderConfig>>(config: LixaConfig<T> & {
|
|
102
202
|
providers: T;
|
|
103
|
-
}): LixaConfig<
|
|
203
|
+
}): LixaConfig<T>;
|
|
104
204
|
/**
|
|
105
205
|
* Generates a cryptographically secure random state parameter for OAuth flows.
|
|
106
206
|
*
|
|
@@ -113,12 +213,81 @@ declare class Lixa<TConfig extends LixaConfig<any> = LixaConfig> {
|
|
|
113
213
|
/**
|
|
114
214
|
* Generates a cryptographically secure code verifier for PKCE flows.
|
|
115
215
|
*
|
|
116
|
-
* @returns A 64-character hexadecimal string
|
|
216
|
+
* @returns A 64-character hexadecimal string (32 random bytes encoded as hex)
|
|
117
217
|
*
|
|
118
218
|
* @remarks
|
|
119
|
-
*
|
|
219
|
+
* This method implements the code verifier generation as specified in RFC 7636 (PKCE).
|
|
220
|
+
*
|
|
221
|
+
* **PKCE (Proof Key for Code Exchange)** is a security extension to OAuth 2.0 that
|
|
222
|
+
* prevents authorization code interception attacks. It's especially important for
|
|
223
|
+
* public clients (mobile apps, SPAs) but is recommended for all OAuth flows.
|
|
224
|
+
*
|
|
225
|
+
* **Generation methodology:**
|
|
226
|
+
* 1. Generate 32 cryptographically random bytes using Node.js crypto.randomBytes()
|
|
227
|
+
* 2. Encode the bytes as a hexadecimal string (64 characters)
|
|
228
|
+
* 3. The verifier is stored securely and used later in the token exchange
|
|
229
|
+
*
|
|
230
|
+
* **RFC 7636 Requirements:**
|
|
231
|
+
* - Minimum length: 43 characters
|
|
232
|
+
* - Maximum length: 128 characters
|
|
233
|
+
* - Character set: [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"
|
|
234
|
+
* - This implementation produces 64 hex characters, meeting the requirements
|
|
235
|
+
*
|
|
236
|
+
* The code verifier is:
|
|
237
|
+
* - Generated when creating the authorization URL
|
|
238
|
+
* - Stored in state cache with the state parameter
|
|
239
|
+
* - Retrieved during callback handling
|
|
240
|
+
* - Sent to the token endpoint to prove the client's identity
|
|
241
|
+
*
|
|
242
|
+
* @see {@link https://datatracker.ietf.org/doc/html/rfc7636 | RFC 7636 - PKCE}
|
|
243
|
+
* @see {@link buildCodeChallenge} for the corresponding challenge generation
|
|
244
|
+
*
|
|
245
|
+
* @internal
|
|
120
246
|
*/
|
|
121
247
|
private static generateCodeVerifier;
|
|
248
|
+
/**
|
|
249
|
+
* Generates a code challenge from a code verifier for PKCE flows.
|
|
250
|
+
*
|
|
251
|
+
* @param codeVerifier - The code verifier string (64 hex characters)
|
|
252
|
+
* @returns A base64url-encoded SHA-256 hash of the code verifier
|
|
253
|
+
*
|
|
254
|
+
* @remarks
|
|
255
|
+
* This method implements the code challenge generation as specified in RFC 7636 (PKCE)
|
|
256
|
+
* using the S256 (SHA-256) transformation method.
|
|
257
|
+
*
|
|
258
|
+
* **Challenge generation methodology:**
|
|
259
|
+
* 1. Hash the code verifier using SHA-256
|
|
260
|
+
* 2. Encode the hash as base64
|
|
261
|
+
* 3. Convert to base64url format (RFC 4648):
|
|
262
|
+
* - Replace '+' with '-'
|
|
263
|
+
* - Replace '/' with '_'
|
|
264
|
+
* - Remove trailing '=' padding
|
|
265
|
+
*
|
|
266
|
+
* **PKCE Flow:**
|
|
267
|
+
* 1. Client generates code_verifier (random string)
|
|
268
|
+
* 2. Client creates code_challenge = BASE64URL(SHA256(code_verifier))
|
|
269
|
+
* 3. Client sends code_challenge to authorization endpoint
|
|
270
|
+
* 4. Authorization server stores the code_challenge
|
|
271
|
+
* 5. Client sends code_verifier to token endpoint
|
|
272
|
+
* 6. Authorization server verifies: SHA256(code_verifier) == code_challenge
|
|
273
|
+
*
|
|
274
|
+
* **Security Benefits:**
|
|
275
|
+
* - Prevents authorization code interception attacks
|
|
276
|
+
* - Even if an attacker intercepts the authorization code, they cannot
|
|
277
|
+
* exchange it for tokens without the original code_verifier
|
|
278
|
+
* - The challenge is sent in the authorization request (public)
|
|
279
|
+
* - The verifier is sent in the token request (should be kept secret)
|
|
280
|
+
*
|
|
281
|
+
* **RFC 7636 Transformation Methods:**
|
|
282
|
+
* - plain: code_challenge = code_verifier (not recommended)
|
|
283
|
+
* - S256: code_challenge = BASE64URL(SHA256(code_verifier)) (recommended, used here)
|
|
284
|
+
*
|
|
285
|
+
* @see {@link https://datatracker.ietf.org/doc/html/rfc7636 | RFC 7636 - PKCE}
|
|
286
|
+
* @see {@link https://datatracker.ietf.org/doc/html/rfc4648#section-5 | RFC 4648 - Base64url Encoding}
|
|
287
|
+
* @see {@link generateCodeVerifier} for the verifier generation
|
|
288
|
+
*
|
|
289
|
+
* @internal
|
|
290
|
+
*/
|
|
122
291
|
private static buildCodeChallenge;
|
|
123
292
|
/**
|
|
124
293
|
* Generates the authorization URL for the specified provider.
|
package/dist/lixa.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lixa.d.ts","sourceRoot":"","sources":["../src/lixa.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAKxC,OAAO,EAAE,KAAK,OAAO,EAAgD,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"lixa.d.ts","sourceRoot":"","sources":["../src/lixa.ts"],"names":[],"mappings":"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"}
|
package/dist/models/session.d.ts
CHANGED
|
@@ -1,27 +1,130 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Represents a user session after successful OAuth authentication.
|
|
3
3
|
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* The Session object is returned by SessionStrategy.createSession() and contains
|
|
6
|
+
* the session identifier and any additional data needed for your application.
|
|
7
|
+
*
|
|
8
|
+
* The structure is intentionally flexible to support various session management
|
|
9
|
+
* approaches (JWT tokens, session IDs, etc.).
|
|
10
|
+
*
|
|
4
11
|
* @public
|
|
5
12
|
*/
|
|
6
13
|
export interface Session {
|
|
7
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* The session token or identifier.
|
|
16
|
+
* This could be an access token, a session ID, a JWT, or any other identifier
|
|
17
|
+
* that your application uses to track authenticated users.
|
|
18
|
+
*/
|
|
8
19
|
token: string;
|
|
9
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Raw session data.
|
|
22
|
+
* Contains the complete OAuth token response and any additional data
|
|
23
|
+
* your SessionStrategy adds (user info, database IDs, etc.).
|
|
24
|
+
*
|
|
25
|
+
* Typical OAuth token data includes:
|
|
26
|
+
* - access_token: OAuth access token
|
|
27
|
+
* - refresh_token: OAuth refresh token (if requested)
|
|
28
|
+
* - expires_in: Token expiration time in seconds
|
|
29
|
+
* - token_type: Token type (usually "Bearer")
|
|
30
|
+
* - id_token: OpenID Connect ID token (if using OIDC)
|
|
31
|
+
* - scope: Granted scopes
|
|
32
|
+
*/
|
|
10
33
|
raw: any;
|
|
11
34
|
}
|
|
12
35
|
/**
|
|
13
36
|
* Strategy interface for custom session creation.
|
|
14
37
|
*
|
|
38
|
+
* @remarks
|
|
39
|
+
* Implement this interface to customize how OAuth tokens are converted into
|
|
40
|
+
* application sessions. This is where you typically:
|
|
41
|
+
* - Decode ID tokens (for OpenID Connect)
|
|
42
|
+
* - Look up or create users in your database
|
|
43
|
+
* - Generate session identifiers
|
|
44
|
+
* - Store session data
|
|
45
|
+
* - Add custom claims or metadata
|
|
46
|
+
*
|
|
47
|
+
* The default implementation (DefaultSessionStrategy) simply extracts the
|
|
48
|
+
* access token and returns it as the session token.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* Custom session strategy with database integration:
|
|
52
|
+
* ```typescript
|
|
53
|
+
* class DatabaseSessionStrategy implements SessionStrategy {
|
|
54
|
+
* constructor(private db: Database) {}
|
|
55
|
+
*
|
|
56
|
+
* async createSession(tokenData: any): Promise<Session> {
|
|
57
|
+
* // Decode ID token for OIDC providers
|
|
58
|
+
* const idToken = tokenData.id_token;
|
|
59
|
+
* const payload = decodeJwt(idToken);
|
|
60
|
+
*
|
|
61
|
+
* // Create or update user in database
|
|
62
|
+
* const user = await this.db.users.upsert({
|
|
63
|
+
* email: payload.email,
|
|
64
|
+
* name: payload.name,
|
|
65
|
+
* picture: payload.picture
|
|
66
|
+
* });
|
|
67
|
+
*
|
|
68
|
+
* // Generate session ID
|
|
69
|
+
* const sessionId = generateSecureId();
|
|
70
|
+
*
|
|
71
|
+
* // Store session with tokens
|
|
72
|
+
* await this.db.sessions.create({
|
|
73
|
+
* id: sessionId,
|
|
74
|
+
* userId: user.id,
|
|
75
|
+
* accessToken: tokenData.access_token,
|
|
76
|
+
* refreshToken: tokenData.refresh_token,
|
|
77
|
+
* expiresAt: new Date(Date.now() + tokenData.expires_in * 1000)
|
|
78
|
+
* });
|
|
79
|
+
*
|
|
80
|
+
* return {
|
|
81
|
+
* token: sessionId,
|
|
82
|
+
* raw: {
|
|
83
|
+
* userId: user.id,
|
|
84
|
+
* email: user.email,
|
|
85
|
+
* ...tokenData
|
|
86
|
+
* }
|
|
87
|
+
* };
|
|
88
|
+
* }
|
|
89
|
+
* }
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
15
92
|
* @public
|
|
16
93
|
*/
|
|
17
94
|
export interface SessionStrategy {
|
|
18
95
|
/**
|
|
19
96
|
* Creates a session from OAuth token data.
|
|
20
97
|
*
|
|
21
|
-
* @param
|
|
98
|
+
* @param tokenData - The token data received from the OAuth provider's token endpoint
|
|
22
99
|
* @returns A Promise that resolves to a Session object
|
|
100
|
+
*
|
|
101
|
+
* @remarks
|
|
102
|
+
* This method is called after successfully exchanging the authorization code
|
|
103
|
+
* for tokens. The tokenData parameter contains the raw response from the
|
|
104
|
+
* provider's token endpoint.
|
|
105
|
+
*
|
|
106
|
+
* Common token data fields:
|
|
107
|
+
* - access_token: OAuth access token
|
|
108
|
+
* - refresh_token: OAuth refresh token (optional)
|
|
109
|
+
* - expires_in: Token expiration time in seconds
|
|
110
|
+
* - token_type: Token type (usually "Bearer")
|
|
111
|
+
* - id_token: OpenID Connect ID token (for OIDC providers)
|
|
112
|
+
* - scope: Granted scopes
|
|
113
|
+
*
|
|
114
|
+
* @throws \{Error\} If session creation fails (e.g., database error, invalid token)
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* Simple implementation:
|
|
118
|
+
* ```typescript
|
|
119
|
+
* async createSession(tokenData: any): Promise<Session> {
|
|
120
|
+
* return {
|
|
121
|
+
* token: tokenData.access_token,
|
|
122
|
+
* raw: tokenData
|
|
123
|
+
* };
|
|
124
|
+
* }
|
|
125
|
+
* ```
|
|
23
126
|
*/
|
|
24
|
-
createSession(
|
|
127
|
+
createSession(tokenData: any): Promise<Session>;
|
|
25
128
|
}
|
|
26
129
|
/**
|
|
27
130
|
* Default session strategy that works with any OAuth provider.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/models/session.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/models/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,OAAO;IACtB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;;;;;;;;;;OAYG;IACH,GAAG,EAAE,GAAG,CAAC;CACV;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,aAAa,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACjD;AAED;;;;;GAKG;AACH,qBAAa,sBAAuB,YAAW,eAAe;IAC5D;;;;;;OAMG;IACG,aAAa,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC;CAgBtD"}
|
|
@@ -1,17 +1,134 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Interface for OAuth provider implementations.
|
|
2
|
+
* Interface for OAuth 2.0 and OpenID Connect provider implementations.
|
|
3
3
|
*
|
|
4
4
|
* @remarks
|
|
5
5
|
* Implement this interface to add support for custom OAuth providers.
|
|
6
|
+
* Each provider defines the three core endpoints required for the OAuth 2.0
|
|
7
|
+
* authorization code flow with PKCE.
|
|
8
|
+
*
|
|
9
|
+
* Built-in providers (Google, GitHub) are available in the \@vunexa/lixa-providers package.
|
|
10
|
+
*
|
|
11
|
+
* All implementations must comply with:
|
|
12
|
+
* - RFC 6749 (OAuth 2.0)
|
|
13
|
+
* - RFC 7636 (PKCE)
|
|
14
|
+
* - OpenID Connect Core 1.0 (for OIDC providers)
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* Custom provider implementation:
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { IProvider } from '@vunexa/lixa';
|
|
20
|
+
*
|
|
21
|
+
* class CustomProvider implements IProvider {
|
|
22
|
+
* authorizationEndpoint = 'https://auth.example.com/oauth/authorize';
|
|
23
|
+
* tokenEndpoint = 'https://auth.example.com/oauth/token';
|
|
24
|
+
* userInfoEndpoint = 'https://api.example.com/user';
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* // Use in configuration
|
|
28
|
+
* const lixa = new Lixa({
|
|
29
|
+
* providers: {
|
|
30
|
+
* custom: {
|
|
31
|
+
* provider: new CustomProvider(),
|
|
32
|
+
* clientId: 'your-client-id',
|
|
33
|
+
* clientSecret: 'your-client-secret',
|
|
34
|
+
* redirectUri: 'https://app.com/callback',
|
|
35
|
+
* scopes: ['read:user']
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* });
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* Object literal provider:
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const customProvider: IProvider = {
|
|
45
|
+
* authorizationEndpoint: 'https://auth.example.com/oauth/authorize',
|
|
46
|
+
* tokenEndpoint: 'https://auth.example.com/oauth/token',
|
|
47
|
+
* userInfoEndpoint: 'https://api.example.com/user'
|
|
48
|
+
* };
|
|
49
|
+
* ```
|
|
6
50
|
*
|
|
7
51
|
* @public
|
|
8
52
|
*/
|
|
9
53
|
interface IProvider {
|
|
10
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* The OAuth 2.0 authorization endpoint URL.
|
|
56
|
+
*
|
|
57
|
+
* @remarks
|
|
58
|
+
* This is the URL where users are redirected to authenticate and authorize your application.
|
|
59
|
+
* The endpoint must support the OAuth 2.0 authorization code flow with PKCE.
|
|
60
|
+
*
|
|
61
|
+
* Standard query parameters sent to this endpoint:
|
|
62
|
+
* - client_id: Your application's client ID
|
|
63
|
+
* - redirect_uri: Where to redirect after authorization
|
|
64
|
+
* - response_type: Always "code" for authorization code flow
|
|
65
|
+
* - scope: Space-separated list of requested scopes
|
|
66
|
+
* - state: Random string for CSRF protection
|
|
67
|
+
* - code_challenge: PKCE code challenge (SHA-256 hash)
|
|
68
|
+
* - code_challenge_method: Always "S256" for SHA-256
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* authorizationEndpoint = 'https://accounts.google.com/o/oauth2/v2/auth'
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
11
75
|
authorizationEndpoint: string;
|
|
12
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* The OAuth 2.0 token endpoint URL.
|
|
78
|
+
*
|
|
79
|
+
* @remarks
|
|
80
|
+
* This is the URL where authorization codes are exchanged for access tokens.
|
|
81
|
+
* The endpoint must support the OAuth 2.0 token exchange with PKCE.
|
|
82
|
+
*
|
|
83
|
+
* Standard parameters sent to this endpoint (POST request):
|
|
84
|
+
* - grant_type: Always "authorization_code"
|
|
85
|
+
* - code: The authorization code from the callback
|
|
86
|
+
* - redirect_uri: Must match the authorization request
|
|
87
|
+
* - client_id: Your application's client ID
|
|
88
|
+
* - client_secret: Your application's client secret
|
|
89
|
+
* - code_verifier: PKCE code verifier (original random string)
|
|
90
|
+
*
|
|
91
|
+
* Expected response:
|
|
92
|
+
* - access_token: OAuth access token
|
|
93
|
+
* - token_type: Token type (usually "Bearer")
|
|
94
|
+
* - expires_in: Token expiration time in seconds
|
|
95
|
+
* - refresh_token: Refresh token (optional)
|
|
96
|
+
* - id_token: OpenID Connect ID token (for OIDC providers)
|
|
97
|
+
* - scope: Granted scopes
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* tokenEndpoint = 'https://oauth2.googleapis.com/token'
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
13
104
|
tokenEndpoint: string;
|
|
14
|
-
/**
|
|
105
|
+
/**
|
|
106
|
+
* The user information endpoint URL.
|
|
107
|
+
*
|
|
108
|
+
* @remarks
|
|
109
|
+
* This is the URL where user profile information can be retrieved using the access token.
|
|
110
|
+
* For OpenID Connect providers, this is the UserInfo endpoint.
|
|
111
|
+
*
|
|
112
|
+
* The endpoint is called with the access token in the Authorization header:
|
|
113
|
+
* ```
|
|
114
|
+
* Authorization: Bearer <access_token>
|
|
115
|
+
* ```
|
|
116
|
+
*
|
|
117
|
+
* Common response fields:
|
|
118
|
+
* - sub: Subject identifier (user ID)
|
|
119
|
+
* - email: User's email address
|
|
120
|
+
* - name: User's full name
|
|
121
|
+
* - picture: User's profile picture URL
|
|
122
|
+
* - email_verified: Whether email is verified
|
|
123
|
+
*
|
|
124
|
+
* Note: This endpoint is not called automatically by Lixa. Your SessionStrategy
|
|
125
|
+
* can call it if needed to fetch user profile information.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* userInfoEndpoint = 'https://www.googleapis.com/oauth2/v2/userinfo'
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
15
132
|
userInfoEndpoint: string;
|
|
16
133
|
}
|
|
17
134
|
export { IProvider };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IProvider.d.ts","sourceRoot":"","sources":["../../src/providers/IProvider.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"IProvider.d.ts","sourceRoot":"","sources":["../../src/providers/IProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,UAAU,SAAS;IACjB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,qBAAqB,EAAE,MAAM,CAAC;IAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
|