@vunexa/lixa 0.0.1-alpha.12 → 0.0.1-alpha.14
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 +31 -28
- package/dist/dao/session-cache.cjs +24 -0
- package/dist/dao/session-cache.d.ts +10 -0
- package/dist/dao/session-cache.d.ts.map +1 -0
- package/dist/dao/session-cache.js +18 -0
- package/dist/dao/session-cache.js.map +1 -0
- package/dist/dao/state-cache.cjs +24 -0
- package/dist/dao/types.cjs +3 -0
- package/dist/dao/types.d.ts +5 -0
- package/dist/dao/types.d.ts.map +1 -1
- package/dist/export-types/index.d.ts +33 -3
- package/dist/index.cjs +16 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lixa.cjs +295 -0
- package/dist/lixa.d.ts +10 -4
- package/dist/lixa.d.ts.map +1 -1
- package/dist/lixa.js +19 -13
- package/dist/lixa.js.map +1 -1
- package/dist/models/session.cjs +34 -0
- package/dist/models/session.d.ts +42 -0
- package/dist/models/session.d.ts.map +1 -0
- package/dist/models/session.js +30 -0
- package/dist/models/session.js.map +1 -0
- package/dist/providers/IProvider.cjs +3 -0
- package/dist/providers/github.cjs +15 -0
- package/dist/providers/google.cjs +15 -0
- package/dist/providers/index.cjs +8 -0
- package/dist/providers-entry.cjs +27 -0
- package/dist/types.cjs +3 -0
- package/dist/types.d.ts +5 -26
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/constants.cjs +8 -0
- package/package.json +9 -5
package/README.md
CHANGED
|
@@ -36,25 +36,25 @@ yarn add @vunexa/lixa
|
|
|
36
36
|
### 1. Configure lixa with multiple providers
|
|
37
37
|
|
|
38
38
|
```typescript
|
|
39
|
-
import { Lixa } from
|
|
39
|
+
import { Lixa } from "@vunexa/lixa";
|
|
40
40
|
|
|
41
41
|
const lixa = new Lixa({
|
|
42
42
|
providers: {
|
|
43
43
|
google: {
|
|
44
44
|
clientId: process.env.GOOGLE_CLIENT_ID!,
|
|
45
45
|
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
|
|
46
|
-
redirectUri:
|
|
47
|
-
scopes: [
|
|
46
|
+
redirectUri: "https://yourapp.com/auth/google/callback",
|
|
47
|
+
scopes: ["openid", "email", "profile"],
|
|
48
48
|
extraConfig: {
|
|
49
|
-
prompt:
|
|
50
|
-
access_type:
|
|
49
|
+
prompt: "consent",
|
|
50
|
+
access_type: "offline",
|
|
51
51
|
},
|
|
52
52
|
},
|
|
53
53
|
github: {
|
|
54
54
|
clientId: process.env.GITHUB_CLIENT_ID!,
|
|
55
55
|
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
|
|
56
|
-
redirectUri:
|
|
57
|
-
scopes: [
|
|
56
|
+
redirectUri: "https://yourapp.com/auth/github/callback",
|
|
57
|
+
scopes: ["read:user", "user:email"],
|
|
58
58
|
extraConfig: {},
|
|
59
59
|
},
|
|
60
60
|
},
|
|
@@ -64,10 +64,10 @@ const lixa = new Lixa({
|
|
|
64
64
|
createSession: async (tokenData) => {
|
|
65
65
|
// Custom session creation logic
|
|
66
66
|
return {
|
|
67
|
-
token:
|
|
68
|
-
raw: tokenData
|
|
67
|
+
token: "custom-session-token",
|
|
68
|
+
raw: tokenData,
|
|
69
69
|
};
|
|
70
|
-
}
|
|
70
|
+
},
|
|
71
71
|
},
|
|
72
72
|
});
|
|
73
73
|
```
|
|
@@ -78,10 +78,10 @@ const lixa = new Lixa({
|
|
|
78
78
|
app.get("/login", (req, res) => {
|
|
79
79
|
const provider = req.query.provider as string; // 'google' or 'github'
|
|
80
80
|
const state = lixa.generateRandomState();
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
// Store state in session for validation
|
|
83
83
|
req.session.oauthState = state;
|
|
84
|
-
|
|
84
|
+
|
|
85
85
|
const authUrl = lixa.getAuthUrl(provider.toUpperCase(), state);
|
|
86
86
|
res.redirect(authUrl);
|
|
87
87
|
});
|
|
@@ -97,7 +97,7 @@ app.get("/auth/:provider/callback", async (req, res) => {
|
|
|
97
97
|
try {
|
|
98
98
|
// Validate state parameter
|
|
99
99
|
if (state !== req.session.oauthState) {
|
|
100
|
-
throw new Error(
|
|
100
|
+
throw new Error("Invalid state parameter");
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
const session = await lixa.handleCallback({
|
|
@@ -110,9 +110,9 @@ app.get("/auth/:provider/callback", async (req, res) => {
|
|
|
110
110
|
res.cookie("session_token", session.token, {
|
|
111
111
|
httpOnly: true,
|
|
112
112
|
secure: true,
|
|
113
|
-
sameSite:
|
|
113
|
+
sameSite: "strict",
|
|
114
114
|
});
|
|
115
|
-
|
|
115
|
+
|
|
116
116
|
res.redirect("/dashboard");
|
|
117
117
|
} catch (error) {
|
|
118
118
|
console.error("Authentication error:", error);
|
|
@@ -128,29 +128,29 @@ app.get("/auth/:provider/callback", async (req, res) => {
|
|
|
128
128
|
You can register custom OAuth providers by implementing the `IProvider` interface:
|
|
129
129
|
|
|
130
130
|
```typescript
|
|
131
|
-
import { Lixa, IProvider } from
|
|
131
|
+
import { Lixa, IProvider } from "@vunexa/lixa";
|
|
132
132
|
|
|
133
133
|
class CustomProvider implements IProvider {
|
|
134
|
-
authorizationEndpoint =
|
|
135
|
-
tokenEndpoint =
|
|
136
|
-
userInfoEndpoint =
|
|
134
|
+
authorizationEndpoint = "https://custom-provider.com/oauth/authorize";
|
|
135
|
+
tokenEndpoint = "https://custom-provider.com/oauth/token";
|
|
136
|
+
userInfoEndpoint = "https://custom-provider.com/api/user";
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
// Register the custom provider
|
|
140
140
|
Lixa.registerProvider({
|
|
141
|
-
custom: new CustomProvider()
|
|
141
|
+
custom: new CustomProvider(),
|
|
142
142
|
});
|
|
143
143
|
|
|
144
144
|
// Use it in your configuration
|
|
145
145
|
const lixa = new Lixa({
|
|
146
146
|
providers: {
|
|
147
147
|
custom: {
|
|
148
|
-
clientId:
|
|
149
|
-
clientSecret:
|
|
150
|
-
redirectUri:
|
|
151
|
-
scopes: [
|
|
152
|
-
}
|
|
153
|
-
}
|
|
148
|
+
clientId: "your-client-id",
|
|
149
|
+
clientSecret: "your-client-secret",
|
|
150
|
+
redirectUri: "https://yourapp.com/auth/custom/callback",
|
|
151
|
+
scopes: ["read:user"],
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
154
|
});
|
|
155
155
|
```
|
|
156
156
|
|
|
@@ -158,8 +158,8 @@ const lixa = new Lixa({
|
|
|
158
158
|
|
|
159
159
|
```typescript
|
|
160
160
|
// Check if a provider is registered
|
|
161
|
-
if (Lixa.isProviderRegistered(
|
|
162
|
-
console.log(
|
|
161
|
+
if (Lixa.isProviderRegistered("google")) {
|
|
162
|
+
console.log("Google provider is available");
|
|
163
163
|
}
|
|
164
164
|
```
|
|
165
165
|
|
|
@@ -168,13 +168,16 @@ if (Lixa.isProviderRegistered('google')) {
|
|
|
168
168
|
### `Lixa` Class
|
|
169
169
|
|
|
170
170
|
#### Constructor
|
|
171
|
+
|
|
171
172
|
- `new Lixa(config: LixaConfig)` - Creates a new Lixa instance
|
|
172
173
|
|
|
173
174
|
#### Static Methods
|
|
175
|
+
|
|
174
176
|
- `Lixa.registerProvider(providerMap: { [key: string]: IProvider })` - Register custom providers
|
|
175
177
|
- `Lixa.isProviderRegistered(provider: string): boolean` - Check if a provider is registered
|
|
176
178
|
|
|
177
179
|
#### Instance Methods
|
|
180
|
+
|
|
178
181
|
- `generateRandomState(): string` - Generate a random state parameter for OAuth flow
|
|
179
182
|
- `getAuthUrl(provider: string, state: string): string` - Get authorization URL for a provider
|
|
180
183
|
- `handleCallback({ provider, code, state }): Promise<Session>` - Handle OAuth callback and create session
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.LocalSessionCache = void 0;
|
|
7
|
+
const node_cache_1 = __importDefault(require("node-cache"));
|
|
8
|
+
class LocalSessionCache {
|
|
9
|
+
cache;
|
|
10
|
+
constructor(defaultTtlSeconds = 600) {
|
|
11
|
+
this.cache = new node_cache_1.default({ stdTTL: defaultTtlSeconds });
|
|
12
|
+
}
|
|
13
|
+
async saveSession(state, data, expiresInSeconds) {
|
|
14
|
+
this.cache.set(state, data, expiresInSeconds);
|
|
15
|
+
}
|
|
16
|
+
async getSession(state) {
|
|
17
|
+
return this.cache.get(state) || null;
|
|
18
|
+
}
|
|
19
|
+
async deleteSession(state) {
|
|
20
|
+
this.cache.del(state);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.LocalSessionCache = LocalSessionCache;
|
|
24
|
+
//# sourceMappingURL=session-cache.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SessionDao } from "./types";
|
|
2
|
+
declare class LocalSessionCache implements SessionDao {
|
|
3
|
+
private cache;
|
|
4
|
+
constructor(defaultTtlSeconds?: number);
|
|
5
|
+
saveSession(state: string, data: any, expiresInSeconds: number): Promise<void>;
|
|
6
|
+
getSession(state: string): Promise<any | null>;
|
|
7
|
+
deleteSession(state: string): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export { LocalSessionCache };
|
|
10
|
+
//# sourceMappingURL=session-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-cache.d.ts","sourceRoot":"","sources":["../../src/dao/session-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,cAAM,iBAAkB,YAAW,UAAU;IAC3C,OAAO,CAAC,KAAK,CAAY;gBAEb,iBAAiB,GAAE,MAAY;IAIrC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9E,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAI9C,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGlD;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import NodeCache from 'node-cache';
|
|
2
|
+
class LocalSessionCache {
|
|
3
|
+
cache;
|
|
4
|
+
constructor(defaultTtlSeconds = 600) {
|
|
5
|
+
this.cache = new NodeCache({ stdTTL: defaultTtlSeconds });
|
|
6
|
+
}
|
|
7
|
+
async saveSession(state, data, expiresInSeconds) {
|
|
8
|
+
this.cache.set(state, data, expiresInSeconds);
|
|
9
|
+
}
|
|
10
|
+
async getSession(state) {
|
|
11
|
+
return this.cache.get(state) || null;
|
|
12
|
+
}
|
|
13
|
+
async deleteSession(state) {
|
|
14
|
+
this.cache.del(state);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export { LocalSessionCache };
|
|
18
|
+
//# sourceMappingURL=session-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-cache.js","sourceRoot":"","sources":["../../src/dao/session-cache.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,YAAY,CAAC;AAGnC,MAAM,iBAAiB;IACb,KAAK,CAAY;IAEzB,YAAY,oBAA4B,GAAG;QACzC,IAAI,CAAC,KAAK,GAAG,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAa,EAAE,IAAS,EAAE,gBAAwB;QAClE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,KAAa;QAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAAa;QAC/B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;CACF;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.LocalStateCache = void 0;
|
|
7
|
+
const node_cache_1 = __importDefault(require("node-cache"));
|
|
8
|
+
class LocalStateCache {
|
|
9
|
+
cache;
|
|
10
|
+
constructor(defaultTtlSeconds = 600) {
|
|
11
|
+
this.cache = new node_cache_1.default({ stdTTL: defaultTtlSeconds });
|
|
12
|
+
}
|
|
13
|
+
async saveState(state, data, expiresInSeconds) {
|
|
14
|
+
this.cache.set(state, data, expiresInSeconds);
|
|
15
|
+
}
|
|
16
|
+
async getState(state) {
|
|
17
|
+
return this.cache.get(state) || null;
|
|
18
|
+
}
|
|
19
|
+
async deleteState(state) {
|
|
20
|
+
this.cache.del(state);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.LocalStateCache = LocalStateCache;
|
|
24
|
+
//# sourceMappingURL=state-cache.js.map
|
package/dist/dao/types.d.ts
CHANGED
|
@@ -3,4 +3,9 @@ export interface StateDao {
|
|
|
3
3
|
getState(state: string): Promise<any | null>;
|
|
4
4
|
deleteState(state: string): Promise<void>;
|
|
5
5
|
}
|
|
6
|
+
export interface SessionDao {
|
|
7
|
+
saveSession(session: string, data: any, expiresInSeconds: number): Promise<void>;
|
|
8
|
+
getSession(session: string): Promise<any | null>;
|
|
9
|
+
deleteSession(session: string): Promise<void>;
|
|
10
|
+
}
|
|
6
11
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/dao/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/dao/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAC7C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/dao/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAC7C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjF,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACjD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C"}
|
|
@@ -12,6 +12,23 @@
|
|
|
12
12
|
*/
|
|
13
13
|
declare type ConfiguredProviderKey<T extends LixaConfig<any>> = keyof T['providers'];
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Default session strategy that works with any OAuth provider.
|
|
17
|
+
* Extracts common token information and creates a standardized session.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
export declare class DefaultSessionStrategy implements SessionStrategy {
|
|
22
|
+
/**
|
|
23
|
+
* Creates a session from OAuth token data.
|
|
24
|
+
* Handles common OAuth token formats and extracts the access token.
|
|
25
|
+
*
|
|
26
|
+
* @param tokenData - The token data received from the OAuth provider
|
|
27
|
+
* @returns A Promise that resolves to a Session object
|
|
28
|
+
*/
|
|
29
|
+
createSession(tokenData: any): Promise<Session>;
|
|
30
|
+
}
|
|
31
|
+
|
|
15
32
|
/**
|
|
16
33
|
* Interface for OAuth provider implementations.
|
|
17
34
|
*
|
|
@@ -62,8 +79,12 @@ export declare interface IProvider {
|
|
|
62
79
|
export declare class Lixa<TConfig extends LixaConfig<any> = LixaConfig> {
|
|
63
80
|
private static CONFIGURED_PROVIDERS;
|
|
64
81
|
private static LOCAL_STATE_CACHE;
|
|
82
|
+
private static LOCAL_SESSION_CACHE;
|
|
83
|
+
private static DEFAULT_SESSION_STRATEGY;
|
|
65
84
|
private config;
|
|
66
85
|
private stateDao;
|
|
86
|
+
private sesionDao;
|
|
87
|
+
private sessionStrategy;
|
|
67
88
|
/**
|
|
68
89
|
* Creates a new Lixa instance with the provided configuration.
|
|
69
90
|
*
|
|
@@ -160,13 +181,13 @@ export declare class Lixa<TConfig extends LixaConfig<any> = LixaConfig> {
|
|
|
160
181
|
* @param provider - The provider name (must be a configured provider key)
|
|
161
182
|
* @param code - The authorization code from the provider
|
|
162
183
|
* @param state - The state parameter for validation
|
|
163
|
-
* @returns A Promise that resolves to
|
|
184
|
+
* @returns A Promise that resolves to the session ID
|
|
164
185
|
*
|
|
165
186
|
* @throws Error when code or state is missing/invalid, or provider is not configured
|
|
166
187
|
*
|
|
167
188
|
* @example
|
|
168
189
|
* ```typescript
|
|
169
|
-
* const
|
|
190
|
+
* const sessionId = await lixa.handleCallback({
|
|
170
191
|
* provider: 'google',
|
|
171
192
|
* code: req.query.code,
|
|
172
193
|
* state: req.query.state
|
|
@@ -177,7 +198,8 @@ export declare class Lixa<TConfig extends LixaConfig<any> = LixaConfig> {
|
|
|
177
198
|
provider: ConfiguredProviderKey<TConfig> | string;
|
|
178
199
|
code: string;
|
|
179
200
|
state?: string;
|
|
180
|
-
}): Promise<
|
|
201
|
+
}): Promise<string>;
|
|
202
|
+
fetchSessionInfo(sessionId: string): Promise<Session | null>;
|
|
181
203
|
private exchangeCodeForToken;
|
|
182
204
|
private findProviderByType;
|
|
183
205
|
}
|
|
@@ -195,6 +217,8 @@ export declare interface LixaConfig<TRegisteredProviders extends string = string
|
|
|
195
217
|
sessionStrategy?: SessionStrategy;
|
|
196
218
|
/** Optional custom state storage implementation */
|
|
197
219
|
stateDao?: StateDao;
|
|
220
|
+
/** Optiona: custom session storage implementation */
|
|
221
|
+
sessionDao?: SessionDao;
|
|
198
222
|
}
|
|
199
223
|
|
|
200
224
|
/**
|
|
@@ -237,6 +261,12 @@ export declare interface Session {
|
|
|
237
261
|
raw: any;
|
|
238
262
|
}
|
|
239
263
|
|
|
264
|
+
declare interface SessionDao {
|
|
265
|
+
saveSession(session: string, data: any, expiresInSeconds: number): Promise<void>;
|
|
266
|
+
getSession(session: string): Promise<any | null>;
|
|
267
|
+
deleteSession(session: string): Promise<void>;
|
|
268
|
+
}
|
|
269
|
+
|
|
240
270
|
/**
|
|
241
271
|
* Strategy interface for custom session creation.
|
|
242
272
|
*
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* A flexible, provider-agnostic OAuth 2.0 and OpenID Connect (OIDC) client library for backend applications.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* This package simplifies multi-provider authentication flows (e.g., Google, GitHub), supports extensible session management, and enables custom provider registration.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.DefaultSessionStrategy = exports.Lixa = void 0;
|
|
12
|
+
var lixa_1 = require("./lixa");
|
|
13
|
+
Object.defineProperty(exports, "Lixa", { enumerable: true, get: function () { return lixa_1.Lixa; } });
|
|
14
|
+
var session_1 = require("./models/session");
|
|
15
|
+
Object.defineProperty(exports, "DefaultSessionStrategy", { enumerable: true, get: function () { return session_1.DefaultSessionStrategy; } });
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
9
|
export { Lixa } from "./lixa";
|
|
10
|
-
export { type ProviderConfig, type LixaConfig, type
|
|
10
|
+
export { type ProviderConfig, type LixaConfig, type SafeLixaConfig, } from "./types";
|
|
11
|
+
export { type Session, type SessionStrategy, DefaultSessionStrategy } from "./models/session";
|
|
11
12
|
export { type IProvider } from "./providers";
|
|
12
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,cAAc,GACpB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,eAAe,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC9F,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAM9B,OAAO,EAAsC,sBAAsB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/lixa.cjs
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Lixa = void 0;
|
|
7
|
+
const crypto_1 = require("crypto");
|
|
8
|
+
const state_cache_1 = require("./dao/state-cache");
|
|
9
|
+
const crypto_2 = __importDefault(require("crypto"));
|
|
10
|
+
const session_cache_1 = require("./dao/session-cache");
|
|
11
|
+
const session_1 = require("./models/session");
|
|
12
|
+
/**
|
|
13
|
+
* A flexible, provider-agnostic OAuth 2.0 and OpenID Connect (OIDC) client library.
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* Lixa simplifies multi-provider authentication flows and supports extensible session management.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { Lixa } from '@vunexa/lixa';
|
|
21
|
+
* import { GoogleProvider } from '@vunexa/lixa/providers';
|
|
22
|
+
*
|
|
23
|
+
* // Register providers before using them
|
|
24
|
+
* Lixa.registerProvider({ google: new GoogleProvider() });
|
|
25
|
+
*
|
|
26
|
+
* const config = Lixa.createConfig({
|
|
27
|
+
* providers: {
|
|
28
|
+
* google: {
|
|
29
|
+
* clientId: 'your-client-id',
|
|
30
|
+
* clientSecret: 'your-client-secret',
|
|
31
|
+
* redirectUri: 'https://yourapp.com/auth/google/callback',
|
|
32
|
+
* scopes: ['openid', 'email', 'profile']
|
|
33
|
+
* }
|
|
34
|
+
* }
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* const lixa = new Lixa(config);
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
42
|
+
class Lixa {
|
|
43
|
+
static CONFIGURED_PROVIDERS = new Map();
|
|
44
|
+
static LOCAL_STATE_CACHE = new state_cache_1.LocalStateCache();
|
|
45
|
+
static LOCAL_SESSION_CACHE = new session_cache_1.LocalSessionCache();
|
|
46
|
+
static DEFAULT_SESSION_STRATEGY = new session_1.DefaultSessionStrategy();
|
|
47
|
+
config;
|
|
48
|
+
stateDao;
|
|
49
|
+
sesionDao;
|
|
50
|
+
sessionStrategy;
|
|
51
|
+
/**
|
|
52
|
+
* Creates a new Lixa instance with the provided configuration.
|
|
53
|
+
*
|
|
54
|
+
* @param config - The configuration object containing provider settings and optional session strategy
|
|
55
|
+
*/
|
|
56
|
+
constructor(config) {
|
|
57
|
+
// Validate that all providers in config are registered
|
|
58
|
+
const configuredProviders = Object.keys(config.providers);
|
|
59
|
+
const registeredProviders = Lixa.getRegisteredProviders();
|
|
60
|
+
for (const provider of configuredProviders) {
|
|
61
|
+
if (!registeredProviders.includes(provider.toLowerCase())) {
|
|
62
|
+
throw new Error(`Provider '${provider}' is not registered. Please register it first using Lixa.registerProvider()`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
this.config = config;
|
|
66
|
+
this.stateDao = config.stateDao || Lixa.LOCAL_STATE_CACHE;
|
|
67
|
+
this.sesionDao = config.sessionDao || Lixa.LOCAL_SESSION_CACHE;
|
|
68
|
+
this.sessionStrategy = config.sessionStrategy || Lixa.DEFAULT_SESSION_STRATEGY;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Checks if a provider is both registered and configured for this instance.
|
|
72
|
+
* This is a type guard that narrows the provider type for use with getAuthUrl.
|
|
73
|
+
*
|
|
74
|
+
* @param provider - The provider name to check (case-insensitive)
|
|
75
|
+
* @returns True if the provider is registered and configured, false otherwise
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* if (lixa.isProviderConfigured(provider)) {
|
|
80
|
+
* // TypeScript now knows provider is a valid ConfiguredProviderKey
|
|
81
|
+
* const authUrl = lixa.getAuthUrl(provider, state);
|
|
82
|
+
* }
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
isProviderConfigured(provider) {
|
|
86
|
+
const providerType = provider.toLowerCase();
|
|
87
|
+
return Lixa.CONFIGURED_PROVIDERS.has(providerType) &&
|
|
88
|
+
this.config.providers.hasOwnProperty(providerType);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Registers custom OAuth providers for use with Lixa.
|
|
92
|
+
*
|
|
93
|
+
* @param providerMap - A map of provider names to IProvider implementations
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* class CustomProvider implements IProvider {
|
|
98
|
+
* authorizationEndpoint = 'https://custom.com/oauth/authorize';
|
|
99
|
+
* tokenEndpoint = 'https://custom.com/oauth/token';
|
|
100
|
+
* userInfoEndpoint = 'https://custom.com/api/user';
|
|
101
|
+
* }
|
|
102
|
+
*
|
|
103
|
+
* Lixa.registerProvider({ custom: new CustomProvider() });
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
static registerProvider(providerMap) {
|
|
107
|
+
Object.entries(providerMap).forEach(([key, providerImpl]) => {
|
|
108
|
+
Lixa.CONFIGURED_PROVIDERS.set(key.toLowerCase(), providerImpl);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Gets the list of registered provider names.
|
|
113
|
+
*
|
|
114
|
+
* @returns Array of registered provider names
|
|
115
|
+
*/
|
|
116
|
+
static getRegisteredProviders() {
|
|
117
|
+
return Array.from(Lixa.CONFIGURED_PROVIDERS.keys());
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Creates a type-safe configuration that only allows registered providers.
|
|
121
|
+
*
|
|
122
|
+
* @param config - Configuration object with providers that must be registered
|
|
123
|
+
* @returns The same configuration object, but with type safety for registered providers
|
|
124
|
+
*/
|
|
125
|
+
static createConfig(config) {
|
|
126
|
+
// Validate that all providers in config are registered
|
|
127
|
+
const configuredProviders = Object.keys(config.providers);
|
|
128
|
+
const registeredProviders = Lixa.getRegisteredProviders();
|
|
129
|
+
for (const provider of configuredProviders) {
|
|
130
|
+
if (!registeredProviders.includes(provider.toLowerCase())) {
|
|
131
|
+
throw new Error(`Provider '${provider}' is not registered. Please register it first using Lixa.registerProvider()`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return config;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Generates a cryptographically secure random state parameter for OAuth flows.
|
|
138
|
+
*
|
|
139
|
+
* @returns A 32-character hexadecimal string
|
|
140
|
+
*
|
|
141
|
+
* @remarks
|
|
142
|
+
* The state parameter is used to prevent CSRF attacks in OAuth flows.
|
|
143
|
+
*/
|
|
144
|
+
static generateRandomState() {
|
|
145
|
+
return (0, crypto_1.randomBytes)(16).toString("hex");
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Generates a cryptographically secure code verifier for PKCE flows.
|
|
149
|
+
*
|
|
150
|
+
* @returns A 64-character hexadecimal string
|
|
151
|
+
*
|
|
152
|
+
* @remarks
|
|
153
|
+
* The code verifier is used in PKCE (Proof Key for Code Exchange) to enhance security.
|
|
154
|
+
*/
|
|
155
|
+
static generateCodeVerifier() {
|
|
156
|
+
return (0, crypto_1.randomBytes)(32).toString("hex");
|
|
157
|
+
}
|
|
158
|
+
static buildCodeChallenge(codeVerifier) {
|
|
159
|
+
const hash = crypto_2.default
|
|
160
|
+
.createHash("sha256")
|
|
161
|
+
.update(codeVerifier)
|
|
162
|
+
.digest("base64");
|
|
163
|
+
// Convert to base64url
|
|
164
|
+
return hash.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Generates the authorization URL for the specified provider.
|
|
168
|
+
*
|
|
169
|
+
* @param provider - The provider name (must be a configured provider key)
|
|
170
|
+
* @param state - The state parameter for CSRF protection
|
|
171
|
+
* @returns The complete authorization URL to redirect users to
|
|
172
|
+
*
|
|
173
|
+
* @throws Error when the provider is not configured
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* const state = Lixa.generateRandomState();
|
|
178
|
+
* const authUrl = lixa.getAuthUrl('google', state);
|
|
179
|
+
* res.redirect(authUrl);
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
getAuthUrl(provider, state) {
|
|
183
|
+
const providerType = String(provider).toLowerCase();
|
|
184
|
+
const providerConfig = this.findProviderByType(providerType);
|
|
185
|
+
const providerImpl = Lixa.CONFIGURED_PROVIDERS.get(providerType);
|
|
186
|
+
if (!providerConfig || !providerImpl) {
|
|
187
|
+
throw new Error(`Provider ${providerType} not configured`);
|
|
188
|
+
}
|
|
189
|
+
const codeVerifier = Lixa.generateCodeVerifier();
|
|
190
|
+
const codeChallenge = Lixa.buildCodeChallenge(codeVerifier);
|
|
191
|
+
// Cache the state paramaeter with TTL of 5 minutes (300 seconds)
|
|
192
|
+
// We dont care about value. we are onl interested in key existence
|
|
193
|
+
this.stateDao.saveState(state, {
|
|
194
|
+
createdAt: Date.now(),
|
|
195
|
+
provider: providerType,
|
|
196
|
+
codeVerifier,
|
|
197
|
+
}, 300 // 5 minutes in seconds
|
|
198
|
+
);
|
|
199
|
+
const params = new URLSearchParams({
|
|
200
|
+
client_id: providerConfig.clientId,
|
|
201
|
+
redirect_uri: providerConfig.redirectUri,
|
|
202
|
+
scope: providerConfig.scopes.join(" "),
|
|
203
|
+
state,
|
|
204
|
+
response_type: "code",
|
|
205
|
+
code_challenge: codeChallenge,
|
|
206
|
+
code_challenge_method: "S256",
|
|
207
|
+
...providerConfig.extraConfig,
|
|
208
|
+
});
|
|
209
|
+
return `${providerImpl.authorizationEndpoint}?${params.toString()}`;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Handles the OAuth callback and creates a user session.
|
|
213
|
+
*
|
|
214
|
+
* @param provider - The provider name (must be a configured provider key)
|
|
215
|
+
* @param code - The authorization code from the provider
|
|
216
|
+
* @param state - The state parameter for validation
|
|
217
|
+
* @returns A Promise that resolves to the session ID
|
|
218
|
+
*
|
|
219
|
+
* @throws Error when code or state is missing/invalid, or provider is not configured
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```typescript
|
|
223
|
+
* const sessionId = await lixa.handleCallback({
|
|
224
|
+
* provider: 'google',
|
|
225
|
+
* code: req.query.code,
|
|
226
|
+
* state: req.query.state
|
|
227
|
+
* });
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
async handleCallback({ provider, code, state, }) {
|
|
231
|
+
if (!code || code.trim() === "") {
|
|
232
|
+
throw new Error("Invalid or missing code in callback");
|
|
233
|
+
}
|
|
234
|
+
if (!state || state.trim() === "") {
|
|
235
|
+
throw new Error("Invalid or missing state in callback");
|
|
236
|
+
}
|
|
237
|
+
//Validate state here
|
|
238
|
+
const cachedState = await this.stateDao.getState(state);
|
|
239
|
+
if (!cachedState) {
|
|
240
|
+
throw new Error("Invalid or expired state");
|
|
241
|
+
}
|
|
242
|
+
// State is valid, remove it from cache to prevent reuse
|
|
243
|
+
await this.stateDao.deleteState(state);
|
|
244
|
+
//Get code verifier from cached state
|
|
245
|
+
const codeVerifier = cachedState.codeVerifier;
|
|
246
|
+
const providerType = String(provider).toLowerCase();
|
|
247
|
+
const providerConfig = this.findProviderByType(providerType);
|
|
248
|
+
const providerImpl = Lixa.CONFIGURED_PROVIDERS.get(providerType);
|
|
249
|
+
if (!providerConfig || !providerImpl) {
|
|
250
|
+
throw new Error(`Provider ${String(provider)} not configured`);
|
|
251
|
+
}
|
|
252
|
+
// Exchange code for tokens and fetch user info here.
|
|
253
|
+
const tokens = await this.exchangeCodeForToken(code, providerConfig, providerImpl, codeVerifier);
|
|
254
|
+
const session = await this.sessionStrategy.createSession(tokens);
|
|
255
|
+
// Generate unique session ID
|
|
256
|
+
const sessionId = (0, crypto_1.randomBytes)(32).toString("hex");
|
|
257
|
+
// Store session with 24 hour TTL (86400 seconds)
|
|
258
|
+
await this.sesionDao.saveSession(sessionId, session, 86400);
|
|
259
|
+
return sessionId;
|
|
260
|
+
}
|
|
261
|
+
fetchSessionInfo(sessionId) {
|
|
262
|
+
return this.sesionDao.getSession(sessionId);
|
|
263
|
+
}
|
|
264
|
+
async exchangeCodeForToken(code, providerConfig, providerImpl, codeVerifier) {
|
|
265
|
+
// Build the request body
|
|
266
|
+
const body = {
|
|
267
|
+
client_id: providerConfig.clientId,
|
|
268
|
+
client_secret: providerConfig.clientSecret,
|
|
269
|
+
code,
|
|
270
|
+
redirect_uri: providerConfig.redirectUri,
|
|
271
|
+
grant_type: "authorization_code",
|
|
272
|
+
};
|
|
273
|
+
if (codeVerifier) {
|
|
274
|
+
body.code_verifier = codeVerifier;
|
|
275
|
+
}
|
|
276
|
+
const params = new URLSearchParams(body);
|
|
277
|
+
const response = await fetch(providerImpl.tokenEndpoint, {
|
|
278
|
+
method: "POST",
|
|
279
|
+
headers: {
|
|
280
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
281
|
+
Accept: "application/json",
|
|
282
|
+
},
|
|
283
|
+
body: params.toString(),
|
|
284
|
+
});
|
|
285
|
+
if (!response.ok) {
|
|
286
|
+
throw new Error(`Token exchange failed: ${response.status} ${response.statusText}`);
|
|
287
|
+
}
|
|
288
|
+
return response.json();
|
|
289
|
+
}
|
|
290
|
+
findProviderByType(providerType) {
|
|
291
|
+
return this.config.providers[providerType];
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
exports.Lixa = Lixa;
|
|
295
|
+
//# sourceMappingURL=lixa.js.map
|
package/dist/lixa.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type LixaConfig, type ProviderConfig
|
|
1
|
+
import { type LixaConfig, type ProviderConfig } from "./types";
|
|
2
2
|
import { IProvider } from "./providers";
|
|
3
|
+
import { type Session } from "./models/session";
|
|
3
4
|
/**
|
|
4
5
|
* Type representing the keys of configured providers
|
|
5
6
|
*/
|
|
@@ -37,8 +38,12 @@ type ConfiguredProviderKey<T extends LixaConfig<any>> = keyof T['providers'];
|
|
|
37
38
|
declare class Lixa<TConfig extends LixaConfig<any> = LixaConfig> {
|
|
38
39
|
private static CONFIGURED_PROVIDERS;
|
|
39
40
|
private static LOCAL_STATE_CACHE;
|
|
41
|
+
private static LOCAL_SESSION_CACHE;
|
|
42
|
+
private static DEFAULT_SESSION_STRATEGY;
|
|
40
43
|
private config;
|
|
41
44
|
private stateDao;
|
|
45
|
+
private sesionDao;
|
|
46
|
+
private sessionStrategy;
|
|
42
47
|
/**
|
|
43
48
|
* Creates a new Lixa instance with the provided configuration.
|
|
44
49
|
*
|
|
@@ -135,13 +140,13 @@ declare class Lixa<TConfig extends LixaConfig<any> = LixaConfig> {
|
|
|
135
140
|
* @param provider - The provider name (must be a configured provider key)
|
|
136
141
|
* @param code - The authorization code from the provider
|
|
137
142
|
* @param state - The state parameter for validation
|
|
138
|
-
* @returns A Promise that resolves to
|
|
143
|
+
* @returns A Promise that resolves to the session ID
|
|
139
144
|
*
|
|
140
145
|
* @throws Error when code or state is missing/invalid, or provider is not configured
|
|
141
146
|
*
|
|
142
147
|
* @example
|
|
143
148
|
* ```typescript
|
|
144
|
-
* const
|
|
149
|
+
* const sessionId = await lixa.handleCallback({
|
|
145
150
|
* provider: 'google',
|
|
146
151
|
* code: req.query.code,
|
|
147
152
|
* state: req.query.state
|
|
@@ -152,7 +157,8 @@ declare class Lixa<TConfig extends LixaConfig<any> = LixaConfig> {
|
|
|
152
157
|
provider: ConfiguredProviderKey<TConfig> | string;
|
|
153
158
|
code: string;
|
|
154
159
|
state?: string;
|
|
155
|
-
}): Promise<
|
|
160
|
+
}): Promise<string>;
|
|
161
|
+
fetchSessionInfo(sessionId: string): Promise<Session | null>;
|
|
156
162
|
private exchangeCodeForToken;
|
|
157
163
|
private findProviderByType;
|
|
158
164
|
}
|
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,
|
|
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;AAO9F;;GAEG;AACH,KAAK,qBAAqB,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,cAAM,IAAI,CAAC,OAAO,SAAS,UAAU,CAAC,GAAG,CAAC,GAAG,UAAU;IACrD,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAqC;IACxE,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAyB;IACzD,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAA2B;IAC7D,OAAO,CAAC,MAAM,CAAC,wBAAwB,CAAgC;IACvE,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,eAAe,CAAkB;IAEzC;;;;OAIG;gBACS,MAAM,EAAE,OAAO;IAiB3B;;;;;;;;;;;;;;OAcG;IACI,oBAAoB,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,QAAQ,IAAI,CAAC,GAAG,qBAAqB,CAAC,OAAO,CAAC;IAM1G;;;;;;;;;;;;;;;OAeG;WACW,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC,GAAG,IAAI;IAMzF;;;;OAIG;WACW,sBAAsB,IAAI,MAAM,EAAE;IAIhD;;;;;OAKG;WACW,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EACjE,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG;QAAE,SAAS,EAAE,CAAC,CAAA;KAAE,GACtD,UAAU,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAc/B;;;;;;;OAOG;WACW,mBAAmB,IAAI,MAAM;IAI3C;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAInC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAUjC;;;;;;;;;;;;;;;OAeG;IACI,UAAU,CAAC,QAAQ,EAAE,qBAAqB,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAsC3F;;;;;;;;;;;;;;;;;;OAkBG;IACU,cAAc,CAAC,EAC1B,QAAQ,EACR,IAAI,EACJ,KAAK,GACN,EAAE;QACD,QAAQ,EAAE,qBAAqB,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC;QAClD,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,MAAM,CAAC;IAgDZ,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;YAIrD,oBAAoB;IAsClC,OAAO,CAAC,kBAAkB;CAG3B;AAED,OAAO,EAAE,IAAI,EAAE,CAAC"}
|
package/dist/lixa.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { randomBytes } from "crypto";
|
|
2
2
|
import { LocalStateCache } from "./dao/state-cache";
|
|
3
3
|
import crypto from "crypto";
|
|
4
|
+
import { LocalSessionCache } from "./dao/session-cache";
|
|
5
|
+
import { DefaultSessionStrategy } from "./models/session";
|
|
4
6
|
/**
|
|
5
7
|
* A flexible, provider-agnostic OAuth 2.0 and OpenID Connect (OIDC) client library.
|
|
6
8
|
*
|
|
@@ -34,8 +36,12 @@ import crypto from "crypto";
|
|
|
34
36
|
class Lixa {
|
|
35
37
|
static CONFIGURED_PROVIDERS = new Map();
|
|
36
38
|
static LOCAL_STATE_CACHE = new LocalStateCache();
|
|
39
|
+
static LOCAL_SESSION_CACHE = new LocalSessionCache();
|
|
40
|
+
static DEFAULT_SESSION_STRATEGY = new DefaultSessionStrategy();
|
|
37
41
|
config;
|
|
38
42
|
stateDao;
|
|
43
|
+
sesionDao;
|
|
44
|
+
sessionStrategy;
|
|
39
45
|
/**
|
|
40
46
|
* Creates a new Lixa instance with the provided configuration.
|
|
41
47
|
*
|
|
@@ -52,6 +58,8 @@ class Lixa {
|
|
|
52
58
|
}
|
|
53
59
|
this.config = config;
|
|
54
60
|
this.stateDao = config.stateDao || Lixa.LOCAL_STATE_CACHE;
|
|
61
|
+
this.sesionDao = config.sessionDao || Lixa.LOCAL_SESSION_CACHE;
|
|
62
|
+
this.sessionStrategy = config.sessionStrategy || Lixa.DEFAULT_SESSION_STRATEGY;
|
|
55
63
|
}
|
|
56
64
|
/**
|
|
57
65
|
* Checks if a provider is both registered and configured for this instance.
|
|
@@ -200,13 +208,13 @@ class Lixa {
|
|
|
200
208
|
* @param provider - The provider name (must be a configured provider key)
|
|
201
209
|
* @param code - The authorization code from the provider
|
|
202
210
|
* @param state - The state parameter for validation
|
|
203
|
-
* @returns A Promise that resolves to
|
|
211
|
+
* @returns A Promise that resolves to the session ID
|
|
204
212
|
*
|
|
205
213
|
* @throws Error when code or state is missing/invalid, or provider is not configured
|
|
206
214
|
*
|
|
207
215
|
* @example
|
|
208
216
|
* ```typescript
|
|
209
|
-
* const
|
|
217
|
+
* const sessionId = await lixa.handleCallback({
|
|
210
218
|
* provider: 'google',
|
|
211
219
|
* code: req.query.code,
|
|
212
220
|
* state: req.query.state
|
|
@@ -237,17 +245,15 @@ class Lixa {
|
|
|
237
245
|
}
|
|
238
246
|
// Exchange code for tokens and fetch user info here.
|
|
239
247
|
const tokens = await this.exchangeCodeForToken(code, providerConfig, providerImpl, codeVerifier);
|
|
240
|
-
|
|
241
|
-
//
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
return session;
|
|
248
|
+
const session = await this.sessionStrategy.createSession(tokens);
|
|
249
|
+
// Generate unique session ID
|
|
250
|
+
const sessionId = randomBytes(32).toString("hex");
|
|
251
|
+
// Store session with 24 hour TTL (86400 seconds)
|
|
252
|
+
await this.sesionDao.saveSession(sessionId, session, 86400);
|
|
253
|
+
return sessionId;
|
|
254
|
+
}
|
|
255
|
+
fetchSessionInfo(sessionId) {
|
|
256
|
+
return this.sesionDao.getSession(sessionId);
|
|
251
257
|
}
|
|
252
258
|
async exchangeCodeForToken(code, providerConfig, providerImpl, codeVerifier) {
|
|
253
259
|
// Build the request body
|
package/dist/lixa.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lixa.js","sourceRoot":"","sources":["../src/lixa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAGrC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,MAAM,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"lixa.js","sourceRoot":"","sources":["../src/lixa.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultSessionStrategy = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Default session strategy that works with any OAuth provider.
|
|
6
|
+
* Extracts common token information and creates a standardized session.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
class DefaultSessionStrategy {
|
|
11
|
+
/**
|
|
12
|
+
* Creates a session from OAuth token data.
|
|
13
|
+
* Handles common OAuth token formats and extracts the access token.
|
|
14
|
+
*
|
|
15
|
+
* @param tokenData - The token data received from the OAuth provider
|
|
16
|
+
* @returns A Promise that resolves to a Session object
|
|
17
|
+
*/
|
|
18
|
+
async createSession(tokenData) {
|
|
19
|
+
// Extract access token from various possible formats
|
|
20
|
+
const accessToken = tokenData.access_token ||
|
|
21
|
+
tokenData.accessToken ||
|
|
22
|
+
tokenData.token ||
|
|
23
|
+
tokenData;
|
|
24
|
+
if (!accessToken || typeof accessToken !== 'string') {
|
|
25
|
+
throw new Error('No valid access token found in OAuth response');
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
token: accessToken,
|
|
29
|
+
raw: tokenData,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.DefaultSessionStrategy = DefaultSessionStrategy;
|
|
34
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a user session after successful OAuth authentication.
|
|
3
|
+
*
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export interface Session {
|
|
7
|
+
/** The session token (typically the access token) */
|
|
8
|
+
token: string;
|
|
9
|
+
/** Raw token data from the OAuth provider */
|
|
10
|
+
raw: any;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Strategy interface for custom session creation.
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export interface SessionStrategy {
|
|
18
|
+
/**
|
|
19
|
+
* Creates a session from OAuth token data.
|
|
20
|
+
*
|
|
21
|
+
* @param userInfo - The token data received from the OAuth provider
|
|
22
|
+
* @returns A Promise that resolves to a Session object
|
|
23
|
+
*/
|
|
24
|
+
createSession(userInfo: any): Promise<Session>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Default session strategy that works with any OAuth provider.
|
|
28
|
+
* Extracts common token information and creates a standardized session.
|
|
29
|
+
*
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
export declare class DefaultSessionStrategy implements SessionStrategy {
|
|
33
|
+
/**
|
|
34
|
+
* Creates a session from OAuth token data.
|
|
35
|
+
* Handles common OAuth token formats and extracts the access token.
|
|
36
|
+
*
|
|
37
|
+
* @param tokenData - The token data received from the OAuth provider
|
|
38
|
+
* @returns A Promise that resolves to a Session object
|
|
39
|
+
*/
|
|
40
|
+
createSession(tokenData: any): Promise<Session>;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/models/session.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,OAAO;IACtB,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,GAAG,EAAE,GAAG,CAAC;CACV;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,aAAa,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChD;AAED;;;;;GAKG;AACH,qBAAa,sBAAuB,YAAW,eAAe;IAC5D;;;;;;OAMG;IACG,aAAa,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC;CAgBtD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default session strategy that works with any OAuth provider.
|
|
3
|
+
* Extracts common token information and creates a standardized session.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export class DefaultSessionStrategy {
|
|
8
|
+
/**
|
|
9
|
+
* Creates a session from OAuth token data.
|
|
10
|
+
* Handles common OAuth token formats and extracts the access token.
|
|
11
|
+
*
|
|
12
|
+
* @param tokenData - The token data received from the OAuth provider
|
|
13
|
+
* @returns A Promise that resolves to a Session object
|
|
14
|
+
*/
|
|
15
|
+
async createSession(tokenData) {
|
|
16
|
+
// Extract access token from various possible formats
|
|
17
|
+
const accessToken = tokenData.access_token ||
|
|
18
|
+
tokenData.accessToken ||
|
|
19
|
+
tokenData.token ||
|
|
20
|
+
tokenData;
|
|
21
|
+
if (!accessToken || typeof accessToken !== 'string') {
|
|
22
|
+
throw new Error('No valid access token found in OAuth response');
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
token: accessToken,
|
|
26
|
+
raw: tokenData,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/models/session.ts"],"names":[],"mappings":"AA2BA;;;;;GAKG;AACH,MAAM,OAAO,sBAAsB;IACjC;;;;;;OAMG;IACH,KAAK,CAAC,aAAa,CAAC,SAAc;QAChC,qDAAqD;QACrD,MAAM,WAAW,GAAG,SAAS,CAAC,YAAY;YACvB,SAAS,CAAC,WAAW;YACrB,SAAS,CAAC,KAAK;YACf,SAAS,CAAC;QAE7B,IAAI,CAAC,WAAW,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QAED,OAAO;YACL,KAAK,EAAE,WAAW;YAClB,GAAG,EAAE,SAAS;SACf,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GithubProvider = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* GitHub OAuth provider implementation
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
class GithubProvider {
|
|
9
|
+
providerType = "GITHUB";
|
|
10
|
+
authorizationEndpoint = "https://github.com/login/oauth/authorize";
|
|
11
|
+
tokenEndpoint = "https://github.com/login/oauth/access_token";
|
|
12
|
+
userInfoEndpoint = "https://api.github.com/user";
|
|
13
|
+
}
|
|
14
|
+
exports.GithubProvider = GithubProvider;
|
|
15
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GoogleProvider = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Google OAuth provider implementation
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
class GoogleProvider {
|
|
9
|
+
providerType = "GOOGLE";
|
|
10
|
+
authorizationEndpoint = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
11
|
+
tokenEndpoint = "https://oauth2.googleapis.com/token";
|
|
12
|
+
userInfoEndpoint = "https://www.googleapis.com/oauth2/v2/userinfo";
|
|
13
|
+
}
|
|
14
|
+
exports.GoogleProvider = GoogleProvider;
|
|
15
|
+
//# sourceMappingURL=google.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GoogleProvider = exports.GithubProvider = void 0;
|
|
4
|
+
var github_1 = require("./github");
|
|
5
|
+
Object.defineProperty(exports, "GithubProvider", { enumerable: true, get: function () { return github_1.GithubProvider; } });
|
|
6
|
+
var google_1 = require("./google");
|
|
7
|
+
Object.defineProperty(exports, "GoogleProvider", { enumerable: true, get: function () { return google_1.GoogleProvider; } });
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Built-in OAuth providers for Lixa
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Import and register these providers before using them in your Lixa configuration.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { Lixa } from '@vunexa/lixa';
|
|
11
|
+
* import { GoogleProvider, GithubProvider } from '@vunexa/lixa/providers';
|
|
12
|
+
*
|
|
13
|
+
* // Register the providers you want to use
|
|
14
|
+
* Lixa.registerProvider({
|
|
15
|
+
* google: new GoogleProvider(),
|
|
16
|
+
* github: new GithubProvider(),
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @packageDocumentation
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.GithubProvider = exports.GoogleProvider = void 0;
|
|
24
|
+
var providers_1 = require("./providers");
|
|
25
|
+
Object.defineProperty(exports, "GoogleProvider", { enumerable: true, get: function () { return providers_1.GoogleProvider; } });
|
|
26
|
+
Object.defineProperty(exports, "GithubProvider", { enumerable: true, get: function () { return providers_1.GithubProvider; } });
|
|
27
|
+
//# sourceMappingURL=providers-entry.js.map
|
package/dist/types.cjs
ADDED
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { StateDao } from "./dao/types";
|
|
1
|
+
import { SessionDao, StateDao } from "./dao/types";
|
|
2
|
+
import { SessionStrategy } from "./models/session";
|
|
3
|
+
export { SessionStrategy };
|
|
2
4
|
/**
|
|
3
5
|
* Configuration for an OAuth provider.
|
|
4
6
|
*
|
|
@@ -29,31 +31,8 @@ export interface LixaConfig<TRegisteredProviders extends string = string> {
|
|
|
29
31
|
sessionStrategy?: SessionStrategy;
|
|
30
32
|
/** Optional custom state storage implementation */
|
|
31
33
|
stateDao?: StateDao;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
* Strategy interface for custom session creation.
|
|
35
|
-
*
|
|
36
|
-
* @public
|
|
37
|
-
*/
|
|
38
|
-
export interface SessionStrategy {
|
|
39
|
-
/**
|
|
40
|
-
* Creates a session from OAuth token data.
|
|
41
|
-
*
|
|
42
|
-
* @param userInfo - The token data received from the OAuth provider
|
|
43
|
-
* @returns A Promise that resolves to a Session object
|
|
44
|
-
*/
|
|
45
|
-
createSession(userInfo: any): Promise<Session>;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Represents a user session after successful OAuth authentication.
|
|
49
|
-
*
|
|
50
|
-
* @public
|
|
51
|
-
*/
|
|
52
|
-
export interface Session {
|
|
53
|
-
/** The session token (typically the access token) */
|
|
54
|
-
token: string;
|
|
55
|
-
/** Raw token data from the OAuth provider */
|
|
56
|
-
raw: any;
|
|
34
|
+
/** Optiona: custom session storage implementation */
|
|
35
|
+
sessionDao?: SessionDao;
|
|
57
36
|
}
|
|
58
37
|
/**
|
|
59
38
|
* Helper type to create a configuration with only registered providers.
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGnD,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU,CAAC,oBAAoB,SAAS,MAAM,GAAG,MAAM;IACtE,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC,oBAAoB,EAAE,cAAc,CAAC,CAAC;IACxD,gDAAgD;IAChD,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,mDAAmD;IACnD,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,qDAAqD;IACrD,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,MAAM,cAAc,CAAC,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,IAAI,UAAU,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG;IACtH,SAAS,EAAE,UAAU,CAAC;CACvB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GITHUB = exports.GOOGLE = void 0;
|
|
4
|
+
const GOOGLE = "google";
|
|
5
|
+
exports.GOOGLE = GOOGLE;
|
|
6
|
+
const GITHUB = "github";
|
|
7
|
+
exports.GITHUB = GITHUB;
|
|
8
|
+
//# sourceMappingURL=constants.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vunexa/lixa",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.14",
|
|
4
4
|
"description": "Lixa is a flexible, provider-agnostic OAuth and OpenID Connect (OIDC) client library that simplifies multi-provider authentication flows. It supports seamless integration with providers like Google and GitHub, offers extensible session management, and enables dynamic provider resolution based on callback URLs.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"oauth",
|
|
@@ -14,16 +14,20 @@
|
|
|
14
14
|
"exports": {
|
|
15
15
|
".": {
|
|
16
16
|
"types": "./dist/export-types/index.d.ts",
|
|
17
|
-
"import": "./dist/index.js"
|
|
17
|
+
"import": "./dist/index.js",
|
|
18
|
+
"require": "./dist/index.cjs"
|
|
18
19
|
},
|
|
19
20
|
"./providers": {
|
|
20
21
|
"types": "./dist/export-types/providers.d.ts",
|
|
21
|
-
"import": "./dist/providers-entry.js"
|
|
22
|
+
"import": "./dist/providers-entry.js",
|
|
23
|
+
"require": "./dist/providers-entry.cjs"
|
|
22
24
|
}
|
|
23
25
|
},
|
|
24
26
|
"scripts": {
|
|
25
|
-
"build": "
|
|
26
|
-
"
|
|
27
|
+
"build": "npm run build:esm && npm run build:cjs && npm run test && api-extractor run --local && api-extractor run --local --config api-extractor-providers.json",
|
|
28
|
+
"build:esm": "tsc",
|
|
29
|
+
"build:cjs": "tsc --module commonjs --outDir dist-cjs && node scripts/rename-cjs.cjs",
|
|
30
|
+
"clean": "rm -rf dist dist-cjs",
|
|
27
31
|
"prepublishOnly": "npm run clean && npm run build",
|
|
28
32
|
"lint": "eslint src/**/*.ts",
|
|
29
33
|
"lint:fix": "eslint src/**/*.ts --fix",
|