@vunexa/lixa 0.0.1-alpha.3
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/LICENSE +21 -0
- package/README.md +240 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/lixa.d.ts +25 -0
- package/dist/lixa.d.ts.map +1 -0
- package/dist/lixa.js +107 -0
- package/dist/lixa.js.map +1 -0
- package/dist/providers/IProvider.d.ts +7 -0
- package/dist/providers/IProvider.d.ts.map +1 -0
- package/dist/providers/IProvider.js +3 -0
- package/dist/providers/IProvider.js.map +1 -0
- package/dist/providers/github.d.ts +9 -0
- package/dist/providers/github.d.ts.map +1 -0
- package/dist/providers/github.js +8 -0
- package/dist/providers/github.js.map +1 -0
- package/dist/providers/google.d.ts +9 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +8 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/index.d.ts +4 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +3 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/types.d.ts +31 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/constants.d.ts +4 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +4 -0
- package/dist/utils/constants.js.map +1 -0
- package/index.d.ts +63 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [2025] [@vunexa/lixa]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# @vunexa/lixa
|
|
2
|
+
|
|
3
|
+
> Package is in very early stage and can have frequent breaking changes. DO NOT USE it for production
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@vunexa/lixa)
|
|
6
|
+
[](https://www.npmjs.com/package/@vunexa/lixa)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
|
|
9
|
+
A flexible, provider-agnostic OAuth 2.0 and OpenID Connect (OIDC) client library for backend applications.
|
|
10
|
+
@vunexa/lixa simplifies multi-provider authentication flows (e.g., Google, GitHub), supports extensible session management, and enables custom provider registration.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- Multi-provider OAuth/OIDC support with unified API
|
|
17
|
+
- Built-in support for popular providers like Google and GitHub
|
|
18
|
+
- Custom provider registration with extensible provider interface
|
|
19
|
+
- Extensible session management via pluggable strategies
|
|
20
|
+
- PKCE (Proof Key for Code Exchange) support
|
|
21
|
+
- TypeScript-first with strong typing and async/await support
|
|
22
|
+
- 100% test coverage with comprehensive error handling
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install @vunexa/lixa
|
|
30
|
+
# or
|
|
31
|
+
yarn add @vunexa/lixa
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
### 1. Configure lixa with multiple providers
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { Lixa } from '@vunexa/lixa';
|
|
40
|
+
|
|
41
|
+
const lixa = new Lixa({
|
|
42
|
+
providers: {
|
|
43
|
+
google: {
|
|
44
|
+
clientId: process.env.GOOGLE_CLIENT_ID!,
|
|
45
|
+
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
|
|
46
|
+
redirectUri: 'https://yourapp.com/auth/google/callback',
|
|
47
|
+
scopes: ['openid', 'email', 'profile'],
|
|
48
|
+
extraConfig: {
|
|
49
|
+
prompt: 'consent',
|
|
50
|
+
access_type: 'offline',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
github: {
|
|
54
|
+
clientId: process.env.GITHUB_CLIENT_ID!,
|
|
55
|
+
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
|
|
56
|
+
redirectUri: 'https://yourapp.com/auth/github/callback',
|
|
57
|
+
scopes: ['read:user', 'user:email'],
|
|
58
|
+
extraConfig: {},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
// Optional: custom session strategy
|
|
63
|
+
sessionStrategy: {
|
|
64
|
+
createSession: async (tokenData) => {
|
|
65
|
+
// Custom session creation logic
|
|
66
|
+
return {
|
|
67
|
+
token: 'custom-session-token',
|
|
68
|
+
raw: tokenData
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 2. Redirect users to the provider's authorization URL
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
app.get("/login", (req, res) => {
|
|
79
|
+
const provider = req.query.provider as string; // 'google' or 'github'
|
|
80
|
+
const state = lixa.generateRandomState();
|
|
81
|
+
|
|
82
|
+
// Store state in session for validation
|
|
83
|
+
req.session.oauthState = state;
|
|
84
|
+
|
|
85
|
+
const authUrl = lixa.getAuthUrl(provider.toUpperCase(), state);
|
|
86
|
+
res.redirect(authUrl);
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 3. Handle the provider callback and establish a session
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
app.get("/auth/:provider/callback", async (req, res) => {
|
|
94
|
+
const { code, state } = req.query;
|
|
95
|
+
const provider = req.params.provider;
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
// Validate state parameter
|
|
99
|
+
if (state !== req.session.oauthState) {
|
|
100
|
+
throw new Error('Invalid state parameter');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const session = await lixa.handleCallback({
|
|
104
|
+
provider,
|
|
105
|
+
code: code as string,
|
|
106
|
+
state: state as string,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Session established
|
|
110
|
+
res.cookie("session_token", session.token, {
|
|
111
|
+
httpOnly: true,
|
|
112
|
+
secure: true,
|
|
113
|
+
sameSite: 'strict'
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
res.redirect("/dashboard");
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.error("Authentication error:", error);
|
|
119
|
+
res.status(500).send("Authentication failed");
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Advanced Usage
|
|
125
|
+
|
|
126
|
+
### Custom Provider Registration
|
|
127
|
+
|
|
128
|
+
You can register custom OAuth providers by implementing the `IProvider` interface:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { Lixa, IProvider } from '@vunexa/lixa';
|
|
132
|
+
|
|
133
|
+
class CustomProvider implements IProvider {
|
|
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
|
+
}
|
|
138
|
+
|
|
139
|
+
// Register the custom provider
|
|
140
|
+
Lixa.registerProvider({
|
|
141
|
+
custom: new CustomProvider()
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Use it in your configuration
|
|
145
|
+
const lixa = new Lixa({
|
|
146
|
+
providers: {
|
|
147
|
+
custom: {
|
|
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
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Check Provider Registration
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
// Check if a provider is registered
|
|
161
|
+
if (Lixa.isProviderRegistered('google')) {
|
|
162
|
+
console.log('Google provider is available');
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## API Reference
|
|
167
|
+
|
|
168
|
+
### `Lixa` Class
|
|
169
|
+
|
|
170
|
+
#### Constructor
|
|
171
|
+
- `new Lixa(config: LixaConfig)` - Creates a new Lixa instance
|
|
172
|
+
|
|
173
|
+
#### Static Methods
|
|
174
|
+
- `Lixa.registerProvider(providerMap: { [key: string]: IProvider })` - Register custom providers
|
|
175
|
+
- `Lixa.isProviderRegistered(provider: string): boolean` - Check if a provider is registered
|
|
176
|
+
|
|
177
|
+
#### Instance Methods
|
|
178
|
+
- `generateRandomState(): string` - Generate a random state parameter for OAuth flow
|
|
179
|
+
- `getAuthUrl(provider: string, state: string): string` - Get authorization URL for a provider
|
|
180
|
+
- `handleCallback({ provider, code, state }): Promise<Session>` - Handle OAuth callback and create session
|
|
181
|
+
|
|
182
|
+
### Types
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
interface ProviderConfig {
|
|
186
|
+
clientId: string;
|
|
187
|
+
clientSecret: string;
|
|
188
|
+
redirectUri: string;
|
|
189
|
+
scopes: string[];
|
|
190
|
+
extraConfig?: Record<string, any>;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
interface LixaConfig {
|
|
194
|
+
providers: Record<string, ProviderConfig>;
|
|
195
|
+
sessionStrategy?: SessionStrategy;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
interface SessionStrategy {
|
|
199
|
+
createSession(userInfo: any): Promise<Session>;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
interface Session {
|
|
203
|
+
token: string;
|
|
204
|
+
raw: any;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
interface IProvider {
|
|
208
|
+
authorizationEndpoint: string;
|
|
209
|
+
tokenEndpoint: string;
|
|
210
|
+
userInfoEndpoint: string;
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Built-in Providers
|
|
215
|
+
|
|
216
|
+
- **Google** - OAuth 2.0 and OpenID Connect
|
|
217
|
+
- **GitHub** - OAuth 2.0
|
|
218
|
+
|
|
219
|
+
## Development
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
# Install dependencies
|
|
223
|
+
npm install
|
|
224
|
+
|
|
225
|
+
# Run tests
|
|
226
|
+
npm test
|
|
227
|
+
|
|
228
|
+
# Run tests with coverage
|
|
229
|
+
npm run test:coverage
|
|
230
|
+
|
|
231
|
+
# Build the library
|
|
232
|
+
npm run build
|
|
233
|
+
|
|
234
|
+
# Lint code
|
|
235
|
+
npm run lint
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## License
|
|
239
|
+
|
|
240
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,OAAO,GACb,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC"}
|
package/dist/lixa.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type LixaConfig, type Session } from "./types";
|
|
2
|
+
import { IProvider } from "./providers";
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
declare class Lixa {
|
|
7
|
+
private static CONFIGURED_PROVIDERS;
|
|
8
|
+
private config;
|
|
9
|
+
constructor(config: LixaConfig);
|
|
10
|
+
static isProviderRegistered(provider: string): boolean;
|
|
11
|
+
static registerProvider(providerMap: {
|
|
12
|
+
[key: string]: IProvider;
|
|
13
|
+
}): void;
|
|
14
|
+
generateRandomState(): string;
|
|
15
|
+
getAuthUrl(provider: string, state: string): string;
|
|
16
|
+
handleCallback({ provider, code, state, }: {
|
|
17
|
+
provider: string;
|
|
18
|
+
code: string;
|
|
19
|
+
state?: string;
|
|
20
|
+
}): Promise<Session>;
|
|
21
|
+
private exchangeCodeForToken;
|
|
22
|
+
private findProviderByType;
|
|
23
|
+
}
|
|
24
|
+
export { Lixa };
|
|
25
|
+
//# sourceMappingURL=lixa.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lixa.d.ts","sourceRoot":"","sources":["../src/lixa.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAuB,KAAK,OAAO,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAkC,MAAM,aAAa,CAAC;AAGxE;;GAEG;AACH,cAAM,IAAI;IACR,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAqC;IACxE,OAAO,CAAC,MAAM,CAAa;gBAEf,MAAM,EAAE,UAAU;WAUhB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;WAI/C,gBAAgB,CAAC,WAAW,EAAE;QAC1C,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;KAC1B,GAAG,IAAI;IAQD,mBAAmB,IAAI,MAAM;IAI7B,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAqB7C,cAAc,CAAC,EAC1B,QAAQ,EACR,IAAI,EACJ,KAAK,GACN,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,OAAO,CAAC;YAuCN,oBAAoB;IAsClC,OAAO,CAAC,kBAAkB;CAG3B;AAED,OAAO,EAAE,IAAI,EAAE,CAAC"}
|
package/dist/lixa.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { randomBytes } from "crypto";
|
|
2
|
+
import { GithubProvider, GoogleProvider } from "./providers";
|
|
3
|
+
import { GITHUB, GOOGLE } from "./utils/constants";
|
|
4
|
+
/**
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
class Lixa {
|
|
8
|
+
static CONFIGURED_PROVIDERS = new Map();
|
|
9
|
+
config;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
if (!Lixa.CONFIGURED_PROVIDERS.has(GITHUB)) {
|
|
13
|
+
Lixa.CONFIGURED_PROVIDERS.set(GITHUB, new GithubProvider());
|
|
14
|
+
}
|
|
15
|
+
if (!Lixa.CONFIGURED_PROVIDERS.has(GOOGLE)) {
|
|
16
|
+
Lixa.CONFIGURED_PROVIDERS.set(GOOGLE, new GoogleProvider());
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
static isProviderRegistered(provider) {
|
|
20
|
+
return Lixa.CONFIGURED_PROVIDERS.has(provider.toLowerCase());
|
|
21
|
+
}
|
|
22
|
+
static registerProvider(providerMap) {
|
|
23
|
+
// This is a static method, so we can't access instance properties.
|
|
24
|
+
// Instead, we can modify the prototype to add the new provider.
|
|
25
|
+
Object.entries(providerMap).forEach(([key, providerImpl]) => {
|
|
26
|
+
Lixa.CONFIGURED_PROVIDERS.set(key, providerImpl);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
generateRandomState() {
|
|
30
|
+
return randomBytes(16).toString("hex");
|
|
31
|
+
}
|
|
32
|
+
getAuthUrl(provider, state) {
|
|
33
|
+
const providerType = provider.toLowerCase();
|
|
34
|
+
const providerConfig = this.findProviderByType(providerType);
|
|
35
|
+
const providerImpl = Lixa.CONFIGURED_PROVIDERS.get(providerType);
|
|
36
|
+
if (!providerConfig || !providerImpl) {
|
|
37
|
+
throw new Error(`Provider ${providerType} not configured`);
|
|
38
|
+
}
|
|
39
|
+
const params = new URLSearchParams({
|
|
40
|
+
client_id: providerConfig.clientId,
|
|
41
|
+
redirect_uri: providerConfig.redirectUri,
|
|
42
|
+
scope: providerConfig.scopes.join(" "),
|
|
43
|
+
state,
|
|
44
|
+
response_type: "code",
|
|
45
|
+
...providerConfig.extraConfig,
|
|
46
|
+
});
|
|
47
|
+
return `${providerImpl.authorizationEndpoint}?${params.toString()}`;
|
|
48
|
+
}
|
|
49
|
+
async handleCallback({ provider, code, state, }) {
|
|
50
|
+
if (!code || code.trim() === "") {
|
|
51
|
+
throw new Error("Invalid or missing code in callback");
|
|
52
|
+
}
|
|
53
|
+
if (!state || state.trim() === "") {
|
|
54
|
+
throw new Error("Invalid or missing state in callback");
|
|
55
|
+
}
|
|
56
|
+
//TODO: Validate state here
|
|
57
|
+
const providerConfig = this.findProviderByType(provider.toLowerCase());
|
|
58
|
+
const providerImpl = Lixa.CONFIGURED_PROVIDERS.get(provider);
|
|
59
|
+
if (!providerConfig || !providerImpl) {
|
|
60
|
+
throw new Error(`Provider ${provider} not configured`);
|
|
61
|
+
}
|
|
62
|
+
// Exchange code for tokens and fetch user info here.
|
|
63
|
+
const tokens = await this.exchangeCodeForToken(code, providerConfig, providerImpl);
|
|
64
|
+
// For simplicity, we'll just return the tokens as the session.
|
|
65
|
+
// In a real implementation, you'd fetch user info and create a session.
|
|
66
|
+
const session = {
|
|
67
|
+
token: tokens.access_token,
|
|
68
|
+
raw: tokens, // Replace with actual user info
|
|
69
|
+
};
|
|
70
|
+
// If a session strategy is provided, use it to create a session.
|
|
71
|
+
if (this.config.sessionStrategy) {
|
|
72
|
+
return this.config.sessionStrategy.createSession(session.raw);
|
|
73
|
+
}
|
|
74
|
+
return session;
|
|
75
|
+
}
|
|
76
|
+
async exchangeCodeForToken(code, providerConfig, providerImpl, codeVerifier) {
|
|
77
|
+
// Build the request body
|
|
78
|
+
const body = {
|
|
79
|
+
client_id: providerConfig.clientId,
|
|
80
|
+
client_secret: providerConfig.clientSecret,
|
|
81
|
+
code,
|
|
82
|
+
redirect_uri: providerConfig.redirectUri,
|
|
83
|
+
grant_type: "authorization_code",
|
|
84
|
+
};
|
|
85
|
+
if (codeVerifier) {
|
|
86
|
+
body.code_verifier = codeVerifier;
|
|
87
|
+
}
|
|
88
|
+
const params = new URLSearchParams(body);
|
|
89
|
+
const response = await fetch(providerImpl.tokenEndpoint, {
|
|
90
|
+
method: "POST",
|
|
91
|
+
headers: {
|
|
92
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
93
|
+
Accept: "application/json",
|
|
94
|
+
},
|
|
95
|
+
body: params.toString(),
|
|
96
|
+
});
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
throw new Error(`Token exchange failed: ${response.status} ${response.statusText}`);
|
|
99
|
+
}
|
|
100
|
+
return response.json();
|
|
101
|
+
}
|
|
102
|
+
findProviderByType(providerType) {
|
|
103
|
+
return this.config.providers[providerType];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
export { Lixa };
|
|
107
|
+
//# sourceMappingURL=lixa.js.map
|
package/dist/lixa.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lixa.js","sourceRoot":"","sources":["../src/lixa.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IProvider.d.ts","sourceRoot":"","sources":["../../src/providers/IProvider.ts"],"names":[],"mappings":"AAEA,UAAU,SAAS;IACjB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IProvider.js","sourceRoot":"","sources":["../../src/providers/IProvider.ts"],"names":[],"mappings":"AAAA,iEAAiE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { IProvider } from "./IProvider";
|
|
2
|
+
declare class GithubProvider implements IProvider {
|
|
3
|
+
providerType: string;
|
|
4
|
+
authorizationEndpoint: string;
|
|
5
|
+
tokenEndpoint: string;
|
|
6
|
+
userInfoEndpoint: string;
|
|
7
|
+
}
|
|
8
|
+
export { GithubProvider };
|
|
9
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/providers/github.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,cAAM,cAAe,YAAW,SAAS;IACvC,YAAY,SAAY;IACxB,qBAAqB,SAA8C;IACnE,aAAa,SAAiD;IAC9D,gBAAgB,SAAiC;CAClD;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
class GithubProvider {
|
|
2
|
+
providerType = "GITHUB";
|
|
3
|
+
authorizationEndpoint = "https://github.com/login/oauth/authorize";
|
|
4
|
+
tokenEndpoint = "https://github.com/login/oauth/access_token";
|
|
5
|
+
userInfoEndpoint = "https://api.github.com/user";
|
|
6
|
+
}
|
|
7
|
+
export { GithubProvider };
|
|
8
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/providers/github.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc;IAClB,YAAY,GAAG,QAAQ,CAAC;IACxB,qBAAqB,GAAG,0CAA0C,CAAC;IACnE,aAAa,GAAG,6CAA6C,CAAC;IAC9D,gBAAgB,GAAG,6BAA6B,CAAC;CAClD;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { IProvider } from "./IProvider";
|
|
2
|
+
declare class GoogleProvider implements IProvider {
|
|
3
|
+
providerType: string;
|
|
4
|
+
authorizationEndpoint: string;
|
|
5
|
+
tokenEndpoint: string;
|
|
6
|
+
userInfoEndpoint: string;
|
|
7
|
+
}
|
|
8
|
+
export { GoogleProvider };
|
|
9
|
+
//# sourceMappingURL=google.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../src/providers/google.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,cAAM,cAAe,YAAW,SAAS;IACvC,YAAY,SAAY;IACxB,qBAAqB,SAAkD;IACvE,aAAa,SAAyC;IACtD,gBAAgB,SAAmD;CACpE;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
class GoogleProvider {
|
|
2
|
+
providerType = "GOOGLE";
|
|
3
|
+
authorizationEndpoint = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
4
|
+
tokenEndpoint = "https://oauth2.googleapis.com/token";
|
|
5
|
+
userInfoEndpoint = "https://www.googleapis.com/oauth2/v2/userinfo";
|
|
6
|
+
}
|
|
7
|
+
export { GoogleProvider };
|
|
8
|
+
//# sourceMappingURL=google.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.js","sourceRoot":"","sources":["../../src/providers/google.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc;IAClB,YAAY,GAAG,QAAQ,CAAC;IACxB,qBAAqB,GAAG,8CAA8C,CAAC;IACvE,aAAa,GAAG,qCAAqC,CAAC;IACtD,gBAAgB,GAAG,+CAA+C,CAAC;CACpE;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @public
|
|
3
|
+
*/
|
|
4
|
+
export interface ProviderConfig {
|
|
5
|
+
clientId: string;
|
|
6
|
+
clientSecret: string;
|
|
7
|
+
redirectUri: string;
|
|
8
|
+
scopes: string[];
|
|
9
|
+
extraConfig?: Record<string, any>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
export interface LixaConfig {
|
|
15
|
+
providers: Record<string, ProviderConfig>;
|
|
16
|
+
sessionStrategy?: SessionStrategy;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
export interface SessionStrategy {
|
|
22
|
+
createSession(userInfo: any): Promise<Session>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
export interface Session {
|
|
28
|
+
token: string;
|
|
29
|
+
raw: any;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,aAAa,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,GAAG,CAAC;CACV"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,MAAM,WAAW,CAAC;AACxB,QAAA,MAAM,MAAM,WAAW,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,QAAQ,CAAC;AACxB,MAAM,MAAM,GAAG,QAAQ,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
declare interface IProvider {
|
|
2
|
+
authorizationEndpoint: string;
|
|
3
|
+
tokenEndpoint: string;
|
|
4
|
+
userInfoEndpoint: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export declare class Lixa {
|
|
11
|
+
private static CONFIGURED_PROVIDERS;
|
|
12
|
+
private config;
|
|
13
|
+
constructor(config: LixaConfig);
|
|
14
|
+
static isProviderRegistered(provider: string): boolean;
|
|
15
|
+
static registerProvider(providerMap: {
|
|
16
|
+
[key: string]: IProvider;
|
|
17
|
+
}): void;
|
|
18
|
+
generateRandomState(): string;
|
|
19
|
+
getAuthUrl(provider: string, state: string): string;
|
|
20
|
+
handleCallback({ provider, code, state, }: {
|
|
21
|
+
provider: string;
|
|
22
|
+
code: string;
|
|
23
|
+
state?: string;
|
|
24
|
+
}): Promise<Session>;
|
|
25
|
+
private exchangeCodeForToken;
|
|
26
|
+
private findProviderByType;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
export declare interface LixaConfig {
|
|
33
|
+
providers: Record<string, ProviderConfig>;
|
|
34
|
+
sessionStrategy?: SessionStrategy;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export declare interface ProviderConfig {
|
|
41
|
+
clientId: string;
|
|
42
|
+
clientSecret: string;
|
|
43
|
+
redirectUri: string;
|
|
44
|
+
scopes: string[];
|
|
45
|
+
extraConfig?: Record<string, any>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
export declare interface Session {
|
|
52
|
+
token: string;
|
|
53
|
+
raw: any;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
export declare interface SessionStrategy {
|
|
60
|
+
createSession(userInfo: any): Promise<Session>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { }
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vunexa/lixa",
|
|
3
|
+
"version": "0.0.1-alpha.3",
|
|
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
|
+
"keywords": [
|
|
6
|
+
"oauth",
|
|
7
|
+
"oidc"
|
|
8
|
+
],
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": "vamsi",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "dist/index.js",
|
|
13
|
+
"types": "index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./index.d.ts",
|
|
17
|
+
"import": "./dist/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc && npm run test && api-extractor run --local",
|
|
22
|
+
"clean": "rm -rf dist",
|
|
23
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
24
|
+
"lint": "eslint src/**/*.ts",
|
|
25
|
+
"lint:fix": "eslint src/**/*.ts --fix",
|
|
26
|
+
"test": "jest",
|
|
27
|
+
"test:watch": "jest --watch",
|
|
28
|
+
"test:coverage": "jest --coverage",
|
|
29
|
+
"api-extractor": "api-extractor run --local --verbose",
|
|
30
|
+
"publish:alpha": "npm run build && npm version prerelease --preid=alpha && npm publish --tag alpha",
|
|
31
|
+
"publish:beta": "npm run build && npm version prerelease --preid=beta && npm publish --tag beta",
|
|
32
|
+
"publish:stable": "npm run build && npm version patch && npm publish --tag latest"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"index.d.ts",
|
|
37
|
+
"README.md",
|
|
38
|
+
"LICENSE"
|
|
39
|
+
],
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@eslint/js": "^9.35.0",
|
|
42
|
+
"@microsoft/api-extractor": "^7.52.11",
|
|
43
|
+
"@types/jest": "^29.5.12",
|
|
44
|
+
"@types/node": "^24.3.1",
|
|
45
|
+
"@typescript-eslint/eslint-plugin": "^8.42.0",
|
|
46
|
+
"@typescript-eslint/parser": "^8.42.0",
|
|
47
|
+
"eslint": "^9.35.0",
|
|
48
|
+
"globals": "^16.3.0",
|
|
49
|
+
"jest": "^29.7.0",
|
|
50
|
+
"ts-jest": "^29.1.2",
|
|
51
|
+
"typescript": "^5.9.2"
|
|
52
|
+
}
|
|
53
|
+
}
|