@leanmcp/auth 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,11 +5,12 @@ Authentication module for LeanMCP providing token-based authentication decorator
5
5
  ## Features
6
6
 
7
7
  - **@Authenticated decorator** - Protect MCP tools, prompts, and resources with token authentication
8
- - **Multi-provider support** - AWS Cognito (more providers coming soon)
8
+ - **Multi-provider support** - AWS Cognito, Clerk, Auth0
9
9
  - **Method or class-level protection** - Apply to individual methods or entire services
10
10
  - **Automatic token validation** - Validates tokens before method execution
11
11
  - **Custom error handling** - Detailed error codes for different auth failures
12
12
  - **Type-safe** - Full TypeScript support with type inference
13
+ - **OAuth & Session modes** - Support for both session-based and OAuth refresh token flows
13
14
 
14
15
  ## Installation
15
16
 
@@ -24,6 +25,16 @@ For AWS Cognito:
24
25
  npm install @aws-sdk/client-cognito-identity-provider axios jsonwebtoken jwk-to-pem
25
26
  ```
26
27
 
28
+ For Clerk:
29
+ ```bash
30
+ npm install axios jsonwebtoken jwk-to-pem
31
+ ```
32
+
33
+ For Auth0:
34
+ ```bash
35
+ npm install axios jsonwebtoken jwk-to-pem
36
+ ```
37
+
27
38
  ## Quick Start
28
39
 
29
40
  ### 1. Initialize Auth Provider
@@ -169,6 +180,17 @@ try {
169
180
 
170
181
  ## Supported Auth Providers
171
182
 
183
+ ### Provider Comparison
184
+
185
+ | Feature | AWS Cognito | Clerk | Auth0 |
186
+ |---------|-------------|-------|-------|
187
+ | **JWT Verification** | ✅ JWKS | ✅ JWKS | ✅ JWKS |
188
+ | **Refresh Tokens** | ✅ Yes | ✅ Yes (OAuth mode) | ✅ Yes |
189
+ | **Session Mode** | ❌ No | ✅ Yes (default) | ❌ No |
190
+ | **OAuth Mode** | ✅ Yes | ✅ Yes | ✅ Yes |
191
+ | **User Data** | ✅ Yes | ✅ Yes | ✅ Yes |
192
+ | **Setup Complexity** | Low | Low | Low |
193
+
172
194
  ### AWS Cognito
173
195
 
174
196
  ```typescript
@@ -185,10 +207,123 @@ await authProvider.init();
185
207
  - Token must be valid and not expired
186
208
  - Token must be issued by the configured User Pool
187
209
 
210
+ **Environment Variables:**
211
+ ```bash
212
+ AWS_REGION=us-east-1
213
+ COGNITO_USER_POOL_ID=us-east-1_XXXXXXXXX
214
+ COGNITO_CLIENT_ID=your-client-id
215
+ ```
216
+
217
+ ### Clerk
218
+
219
+ Clerk supports both **Session Mode** (default) and **OAuth Mode** (with refresh tokens).
220
+
221
+ #### Session Mode (Default)
222
+
223
+ ```typescript
224
+ const authProvider = new AuthProvider('clerk', {
225
+ frontendApi: 'your-frontend-api.clerk.accounts.dev',
226
+ secretKey: 'sk_test_...'
227
+ });
228
+ await authProvider.init();
229
+ ```
230
+
231
+ **Configuration:**
232
+ - `frontendApi` - Your Clerk Frontend API domain
233
+ - `secretKey` - Your Clerk Secret Key
234
+
235
+ **Environment Variables:**
236
+ ```bash
237
+ CLERK_FRONTEND_API=your-frontend-api.clerk.accounts.dev
238
+ CLERK_SECRET_KEY=sk_test_...
239
+ ```
240
+
241
+ #### OAuth Mode (Refresh Tokens)
242
+
243
+ ```typescript
244
+ const authProvider = new AuthProvider('clerk', {
245
+ frontendApi: 'your-frontend-api.clerk.accounts.dev',
246
+ secretKey: 'sk_test_...',
247
+ clientId: 'your-oauth-client-id',
248
+ clientSecret: 'your-oauth-client-secret',
249
+ redirectUri: 'https://yourapp.com/callback'
250
+ });
251
+ await authProvider.init();
252
+
253
+ // Refresh tokens when needed
254
+ const newTokens = await authProvider.refreshToken(refreshToken);
255
+ // Returns: { access_token, id_token, refresh_token }
256
+ ```
257
+
258
+ **OAuth Configuration:**
259
+ - `clientId` - OAuth Client ID from Clerk
260
+ - `clientSecret` - OAuth Client Secret from Clerk
261
+ - `redirectUri` - OAuth redirect URI
262
+
263
+ **Token Requirements:**
264
+ - JWT token from Clerk (ID token or session token)
265
+ - Token must be valid and not expired
266
+ - Token must be issued by your Clerk instance
267
+
268
+ **User Data:**
269
+ ```typescript
270
+ const user = await authProvider.getUser(idToken);
271
+ // Returns: { sub, email, email_verified, first_name, last_name, attributes }
272
+ ```
273
+
274
+ ### Auth0
275
+
276
+ ```typescript
277
+ const authProvider = new AuthProvider('auth0', {
278
+ domain: 'your-tenant.auth0.com',
279
+ clientId: 'your-client-id',
280
+ clientSecret: 'your-client-secret', // Optional for public clients
281
+ audience: 'https://your-api-identifier',
282
+ scopes: 'openid profile email offline_access' // Optional, defaults shown
283
+ });
284
+ await authProvider.init();
285
+
286
+ // Refresh tokens when needed
287
+ const newTokens = await authProvider.refreshToken(refreshToken);
288
+ // Returns: { access_token, id_token, refresh_token, expires_in }
289
+ ```
290
+
291
+ **Configuration:**
292
+ - `domain` - Your Auth0 tenant domain (e.g., `your-tenant.auth0.com`)
293
+ - `clientId` - Your Auth0 Application Client ID
294
+ - `clientSecret` - Your Auth0 Application Client Secret (optional for public clients)
295
+ - `audience` - Your API identifier (required for API access)
296
+ - `scopes` - OAuth scopes (default: `openid profile email offline_access`)
297
+
298
+ **Environment Variables:**
299
+ ```bash
300
+ AUTH0_DOMAIN=your-tenant.auth0.com
301
+ AUTH0_CLIENT_ID=your-client-id
302
+ AUTH0_CLIENT_SECRET=your-client-secret
303
+ AUTH0_AUDIENCE=https://your-api-identifier
304
+ ```
305
+
306
+ **Token Requirements:**
307
+ - JWT token from Auth0 (access token or ID token)
308
+ - Token must be valid and not expired
309
+ - Token must be issued by your Auth0 tenant
310
+ - Token must have the correct audience
311
+
312
+ **User Data:**
313
+ ```typescript
314
+ const user = await authProvider.getUser(idToken);
315
+ // Returns: { sub, email, email_verified, name, attributes }
316
+ ```
317
+
318
+ **Error Handling:**
319
+ Auth0 provider includes detailed error messages:
320
+ - `Token has expired` - Token is expired
321
+ - `Invalid token signature` - Token signature verification failed
322
+ - `Malformed token` - Token format is invalid
323
+ - `Invalid token issuer` - Token issuer doesn't match
324
+
188
325
  ### More Providers Coming Soon
189
326
 
190
- - Clerk
191
- - Auth0
192
327
  - Firebase Auth
193
328
  - Custom JWT providers
194
329
 
@@ -238,16 +373,32 @@ function getAuthProvider(target: any, propertyKey?: string): AuthProvider | unde
238
373
 
239
374
  ## Environment Variables
240
375
 
241
- For AWS Cognito:
376
+ ### AWS Cognito
242
377
  ```bash
243
378
  AWS_REGION=us-east-1
244
379
  COGNITO_USER_POOL_ID=us-east-1_XXXXXXXXX
245
380
  COGNITO_CLIENT_ID=your-client-id
246
381
  ```
247
382
 
248
- ## Complete Example
383
+ ### Clerk (Session Mode)
384
+ ```bash
385
+ CLERK_FRONTEND_API=your-frontend-api.clerk.accounts.dev
386
+ CLERK_SECRET_KEY=sk_test_...
387
+ ```
388
+
389
+ ### Auth0
390
+ ```bash
391
+ AUTH0_DOMAIN=your-tenant.auth0.com
392
+ AUTH0_CLIENT_ID=your-client-id
393
+ AUTH0_CLIENT_SECRET=your-client-secret
394
+ AUTH0_AUDIENCE=https://your-api-identifier
395
+ ```
249
396
 
250
- See [examples/slack-with-auth](../../examples/slack-with-auth) for a complete working example with AWS Cognito.
397
+ ## Complete Examples
398
+
399
+ ### AWS Cognito Example
400
+
401
+ See [examples/slack-with-auth](../../examples/slack-with-auth) for a complete working example.
251
402
 
252
403
  ```typescript
253
404
  import { createHTTPServer, MCPServer } from "@leanmcp/core";
@@ -280,6 +431,123 @@ const serverFactory = () => {
280
431
  await createHTTPServer(serverFactory, { port: 3000 });
281
432
  ```
282
433
 
434
+ ### Clerk Example
435
+
436
+ ```typescript
437
+ import { createHTTPServer, MCPServer } from "@leanmcp/core";
438
+ import { AuthProvider, Authenticated } from "@leanmcp/auth";
439
+
440
+ // Initialize Clerk in Session Mode
441
+ const authProvider = new AuthProvider('clerk', {
442
+ frontendApi: process.env.CLERK_FRONTEND_API,
443
+ secretKey: process.env.CLERK_SECRET_KEY
444
+ });
445
+ await authProvider.init();
446
+
447
+ // Or initialize in OAuth Mode (with refresh tokens)
448
+ const authProviderOAuth = new AuthProvider('clerk', {
449
+ frontendApi: process.env.CLERK_FRONTEND_API,
450
+ secretKey: process.env.CLERK_SECRET_KEY,
451
+ clientId: process.env.CLERK_CLIENT_ID,
452
+ clientSecret: process.env.CLERK_CLIENT_SECRET,
453
+ redirectUri: process.env.CLERK_REDIRECT_URI
454
+ });
455
+ await authProviderOAuth.init();
456
+
457
+ @Authenticated(authProvider)
458
+ class UserService {
459
+ @Tool({ description: 'Get user profile' })
460
+ async getProfile(input: { userId: string }) {
461
+ // Token is automatically validated
462
+ return { userId: input.userId, name: "John Doe" };
463
+ }
464
+ }
465
+
466
+ const serverFactory = () => {
467
+ const server = new MCPServer({ name: "clerk-server", version: "1.0.0" });
468
+ server.registerService(new UserService());
469
+ return server.getServer();
470
+ };
471
+
472
+ await createHTTPServer(serverFactory, { port: 3000 });
473
+ ```
474
+
475
+ ### Auth0 Example
476
+
477
+ ```typescript
478
+ import { createHTTPServer, MCPServer } from "@leanmcp/core";
479
+ import { AuthProvider, Authenticated } from "@leanmcp/auth";
480
+
481
+ // Initialize Auth0
482
+ const authProvider = new AuthProvider('auth0', {
483
+ domain: process.env.AUTH0_DOMAIN,
484
+ clientId: process.env.AUTH0_CLIENT_ID,
485
+ clientSecret: process.env.AUTH0_CLIENT_SECRET,
486
+ audience: process.env.AUTH0_AUDIENCE,
487
+ scopes: 'openid profile email offline_access'
488
+ });
489
+ await authProvider.init();
490
+
491
+ @Authenticated(authProvider)
492
+ class SecureAPIService {
493
+ @Tool({ description: 'Get sensitive data' })
494
+ async getSensitiveData(input: { dataId: string }) {
495
+ // Token is automatically validated
496
+ return { dataId: input.dataId, data: "Sensitive information" };
497
+ }
498
+
499
+ @Tool({ description: 'Update user settings' })
500
+ async updateSettings(input: { settings: Record<string, any> }) {
501
+ return { success: true, settings: input.settings };
502
+ }
503
+ }
504
+
505
+ const serverFactory = () => {
506
+ const server = new MCPServer({ name: "auth0-server", version: "1.0.0" });
507
+ server.registerService(new SecureAPIService());
508
+ return server.getServer();
509
+ };
510
+
511
+ await createHTTPServer(serverFactory, { port: 3000 });
512
+ ```
513
+
514
+ ### Multi-Provider Example
515
+
516
+ ```typescript
517
+ import { AuthProvider, Authenticated } from "@leanmcp/auth";
518
+
519
+ // Initialize multiple providers
520
+ const clerkAuth = new AuthProvider('clerk', {
521
+ frontendApi: process.env.CLERK_FRONTEND_API,
522
+ secretKey: process.env.CLERK_SECRET_KEY
523
+ });
524
+ await clerkAuth.init();
525
+
526
+ const auth0Auth = new AuthProvider('auth0', {
527
+ domain: process.env.AUTH0_DOMAIN,
528
+ clientId: process.env.AUTH0_CLIENT_ID,
529
+ audience: process.env.AUTH0_AUDIENCE
530
+ });
531
+ await auth0Auth.init();
532
+
533
+ // Use different providers for different services
534
+ @Authenticated(clerkAuth)
535
+ class UserService {
536
+ @Tool()
537
+ async getUserData(input: { userId: string }) {
538
+ return { userId: input.userId };
539
+ }
540
+ }
541
+
542
+ @Authenticated(auth0Auth)
543
+ class AdminService {
544
+ @Tool()
545
+ async getAdminData(input: { adminId: string }) {
546
+ return { adminId: input.adminId };
547
+ }
548
+ }
549
+ ```
550
+
283
551
  ## How It Works
284
552
 
285
553
  1. **Request arrives** with `_meta.authorization.token`
@@ -304,6 +572,85 @@ await createHTTPServer(serverFactory, { port: 3000 });
304
572
  5. **Log authentication failures** - Monitor for suspicious activity
305
573
  6. **Use environment variables** - Never hardcode credentials
306
574
  7. **Use _meta for auth** - Don't include tokens in business arguments
575
+ 8. **Choose the right mode** - Use Session mode for simpler setups, OAuth mode for refresh tokens
576
+ 9. **Test token expiration** - Ensure your app handles expired tokens gracefully
577
+ 10. **Monitor JWKS cache** - Providers cache JWKS keys for performance
578
+
579
+ ## Quick Reference
580
+
581
+ ### Initialization Patterns
582
+
583
+ ```typescript
584
+ // AWS Cognito
585
+ const cognito = new AuthProvider('cognito', {
586
+ region: 'us-east-1',
587
+ userPoolId: 'us-east-1_XXX',
588
+ clientId: 'xxx'
589
+ });
590
+
591
+ // Clerk (Session Mode)
592
+ const clerk = new AuthProvider('clerk', {
593
+ frontendApi: 'xxx.clerk.accounts.dev',
594
+ secretKey: 'sk_test_xxx'
595
+ });
596
+
597
+ // Clerk (OAuth Mode)
598
+ const clerkOAuth = new AuthProvider('clerk', {
599
+ frontendApi: 'xxx.clerk.accounts.dev',
600
+ secretKey: 'sk_test_xxx',
601
+ clientId: 'xxx',
602
+ clientSecret: 'xxx',
603
+ redirectUri: 'https://app.com/callback'
604
+ });
605
+
606
+ // Auth0
607
+ const auth0 = new AuthProvider('auth0', {
608
+ domain: 'tenant.auth0.com',
609
+ clientId: 'xxx',
610
+ clientSecret: 'xxx',
611
+ audience: 'https://api-identifier'
612
+ });
613
+ ```
614
+
615
+ ### Common Operations
616
+
617
+ ```typescript
618
+ // Initialize
619
+ await authProvider.init();
620
+
621
+ // Verify token
622
+ const isValid = await authProvider.verifyToken(token);
623
+
624
+ // Refresh token (OAuth/Auth0 only)
625
+ const newTokens = await authProvider.refreshToken(refreshToken);
626
+
627
+ // Get user data
628
+ const user = await authProvider.getUser(idToken);
629
+
630
+ // Get provider type
631
+ const type = authProvider.getProviderType(); // 'cognito' | 'clerk' | 'auth0'
632
+ ```
633
+
634
+ ### Decorator Usage
635
+
636
+ ```typescript
637
+ // Protect single method
638
+ @Authenticated(authProvider)
639
+ async myMethod(input: { data: string }) { }
640
+
641
+ // Protect entire class
642
+ @Authenticated(authProvider)
643
+ class MyService {
644
+ @Tool() async method1() { }
645
+ @Tool() async method2() { }
646
+ }
647
+
648
+ // Check if authentication required
649
+ const required = isAuthenticationRequired(target, 'methodName');
650
+
651
+ // Get auth provider for method
652
+ const provider = getAuthProvider(target, 'methodName');
653
+ ```
307
654
 
308
655
  ## License
309
656
 
@@ -0,0 +1,102 @@
1
+ import {
2
+ AuthProviderBase,
3
+ __name
4
+ } from "./chunk-KKO5VLFX.mjs";
5
+
6
+ // src/providers/auth0.ts
7
+ import axios from "axios";
8
+ import jwt from "jsonwebtoken";
9
+ import jwkToPem from "jwk-to-pem";
10
+ var AuthAuth0 = class extends AuthProviderBase {
11
+ static {
12
+ __name(this, "AuthAuth0");
13
+ }
14
+ domain = "";
15
+ clientId = "";
16
+ clientSecret = "";
17
+ audience = "";
18
+ scopes = "openid profile email offline_access";
19
+ jwksCache = null;
20
+ async init(config) {
21
+ this.domain = config?.domain || process.env.AUTH0_DOMAIN || "";
22
+ this.clientId = config?.clientId || process.env.AUTH0_CLIENT_ID || "";
23
+ this.clientSecret = config?.clientSecret || process.env.AUTH0_CLIENT_SECRET || "";
24
+ this.audience = config?.audience || process.env.AUTH0_AUDIENCE || "";
25
+ this.scopes = config?.scopes || this.scopes;
26
+ if (!this.domain || !this.clientId || !this.audience) {
27
+ throw new Error("Auth0 config missing: domain, clientId, and audience are required");
28
+ }
29
+ }
30
+ async refreshToken(refreshToken) {
31
+ const url = `https://${this.domain}/oauth/token`;
32
+ const payload = {
33
+ grant_type: "refresh_token",
34
+ client_id: this.clientId,
35
+ refresh_token: refreshToken,
36
+ audience: this.audience,
37
+ scope: this.scopes
38
+ };
39
+ if (this.clientSecret) {
40
+ payload.client_secret = this.clientSecret;
41
+ }
42
+ const { data } = await axios.post(url, payload, {
43
+ headers: {
44
+ "Content-Type": "application/json"
45
+ }
46
+ });
47
+ return data;
48
+ }
49
+ async verifyToken(token) {
50
+ try {
51
+ await this.verifyJwt(token);
52
+ return true;
53
+ } catch (error) {
54
+ if (error instanceof Error) {
55
+ if (error.message.includes("jwt expired")) throw new Error("Token has expired");
56
+ if (error.message.includes("invalid signature")) throw new Error("Invalid token signature");
57
+ if (error.message.includes("jwt malformed")) throw new Error("Malformed token");
58
+ if (error.message.includes("invalid issuer")) throw new Error("Invalid token issuer");
59
+ throw error;
60
+ }
61
+ return false;
62
+ }
63
+ }
64
+ async getUser(idToken) {
65
+ const decoded = jwt.decode(idToken);
66
+ if (!decoded) throw new Error("Invalid ID token");
67
+ return {
68
+ sub: decoded.sub,
69
+ email: decoded.email,
70
+ email_verified: decoded.email_verified,
71
+ name: decoded.name,
72
+ attributes: decoded
73
+ };
74
+ }
75
+ async fetchJWKS() {
76
+ if (!this.jwksCache) {
77
+ const jwksUri = `https://${this.domain}/.well-known/jwks.json`;
78
+ const { data } = await axios.get(jwksUri);
79
+ this.jwksCache = data.keys;
80
+ }
81
+ return this.jwksCache;
82
+ }
83
+ async verifyJwt(token) {
84
+ const decoded = jwt.decode(token, {
85
+ complete: true
86
+ });
87
+ if (!decoded) throw new Error("Invalid token");
88
+ const jwks = await this.fetchJWKS();
89
+ const key = jwks.find((k) => k.kid === decoded.header.kid);
90
+ if (!key) throw new Error("Signing key not found in JWKS");
91
+ const pem = jwkToPem(key);
92
+ return jwt.verify(token, pem, {
93
+ algorithms: [
94
+ "RS256"
95
+ ],
96
+ issuer: `https://${this.domain}/`
97
+ });
98
+ }
99
+ };
100
+ export {
101
+ AuthAuth0
102
+ };
@@ -123,18 +123,23 @@ var AuthProvider = class extends AuthProviderBase {
123
123
  const finalConfig = config || this.config;
124
124
  switch (this.providerType) {
125
125
  case "cognito": {
126
- const { AuthCognito } = await import("./cognito-VCVS77OX.mjs");
126
+ const { AuthCognito } = await import("./cognito-2RRSLFKI.mjs");
127
127
  this.providerInstance = new AuthCognito();
128
128
  await this.providerInstance.init(finalConfig);
129
129
  break;
130
130
  }
131
- // Add more providers here in the future
132
- // case 'clerk': {
133
- // const { AuthClerk } = await import('./providers/clerk');
134
- // this.providerInstance = new AuthClerk();
135
- // await this.providerInstance.init(finalConfig);
136
- // break;
137
- // }
131
+ case "auth0": {
132
+ const { AuthAuth0 } = await import("./auth0-A25F3NOH.mjs");
133
+ this.providerInstance = new AuthAuth0();
134
+ await this.providerInstance.init(finalConfig);
135
+ break;
136
+ }
137
+ case "clerk": {
138
+ const { AuthClerk } = await import("./clerk-XNMGPYSN.mjs");
139
+ this.providerInstance = new AuthClerk();
140
+ await this.providerInstance.init(finalConfig);
141
+ break;
142
+ }
138
143
  default:
139
144
  throw new Error(`Unsupported auth provider: ${this.providerType}. Supported providers: cognito`);
140
145
  }
@@ -0,0 +1,115 @@
1
+ import {
2
+ AuthProviderBase,
3
+ __name
4
+ } from "./chunk-KKO5VLFX.mjs";
5
+
6
+ // src/providers/clerk.ts
7
+ import axios from "axios";
8
+ import jwt from "jsonwebtoken";
9
+ import jwkToPem from "jwk-to-pem";
10
+ var AuthClerk = class extends AuthProviderBase {
11
+ static {
12
+ __name(this, "AuthClerk");
13
+ }
14
+ clerkFrontendApi = "";
15
+ clerkSecretKey = "";
16
+ clerkJWKSUrl = "";
17
+ clerkIssuer = "";
18
+ jwksCache = null;
19
+ mode = "session";
20
+ oauthTokenUrl = "";
21
+ clientId;
22
+ clientSecret;
23
+ redirectUri;
24
+ /**
25
+ * Initialize Clerk Auth Provider
26
+ */
27
+ async init(config) {
28
+ this.clerkFrontendApi = config?.frontendApi || process.env.CLERK_FRONTEND_API || "";
29
+ this.clerkSecretKey = config?.secretKey || process.env.CLERK_SECRET_KEY || "";
30
+ if (!this.clerkFrontendApi || !this.clerkSecretKey) {
31
+ throw new Error("Missing Clerk configuration: frontendApi and secretKey are required");
32
+ }
33
+ this.clerkIssuer = `https://${this.clerkFrontendApi}`;
34
+ this.clerkJWKSUrl = `${this.clerkIssuer}/.well-known/jwks.json`;
35
+ if (config?.clientId && config?.clientSecret && config?.redirectUri) {
36
+ this.mode = "oauth";
37
+ this.clientId = config.clientId;
38
+ this.clientSecret = config.clientSecret;
39
+ this.redirectUri = config.redirectUri;
40
+ this.oauthTokenUrl = `${this.clerkIssuer}/oauth/token`;
41
+ }
42
+ }
43
+ /**
44
+ * Refresh tokens (OAuth mode only)
45
+ */
46
+ async refreshToken(refreshToken) {
47
+ if (this.mode !== "oauth") {
48
+ throw new Error("Clerk is in Session Mode: refresh tokens are not supported. Enable OAuth mode.");
49
+ }
50
+ const payload = {
51
+ grant_type: "refresh_token",
52
+ refresh_token: refreshToken,
53
+ client_id: this.clientId,
54
+ client_secret: this.clientSecret,
55
+ redirect_uri: this.redirectUri
56
+ };
57
+ const { data } = await axios.post(this.oauthTokenUrl, payload, {
58
+ headers: {
59
+ "Content-Type": "application/json"
60
+ }
61
+ });
62
+ return data;
63
+ }
64
+ /**
65
+ * Verify JWT using JWKS
66
+ */
67
+ async verifyToken(token) {
68
+ await this.verifyJwt(token);
69
+ return true;
70
+ }
71
+ /**
72
+ * Extract user data from ID token
73
+ */
74
+ async getUser(idToken) {
75
+ const decoded = jwt.decode(idToken);
76
+ if (!decoded) throw new Error("Invalid ID token");
77
+ return {
78
+ sub: decoded.sub,
79
+ email: decoded.email,
80
+ email_verified: decoded.email_verified,
81
+ first_name: decoded.given_name,
82
+ last_name: decoded.family_name,
83
+ attributes: decoded
84
+ };
85
+ }
86
+ /**
87
+ * JWT verification using JWKS
88
+ */
89
+ async verifyJwt(token) {
90
+ const decoded = jwt.decode(token, {
91
+ complete: true
92
+ });
93
+ if (!decoded) throw new Error("Invalid token");
94
+ const jwks = await this.fetchJWKS();
95
+ const key = jwks.find((k) => k.kid === decoded.header.kid);
96
+ if (!key) throw new Error("Signing key not found in JWKS");
97
+ const pem = jwkToPem(key);
98
+ return jwt.verify(token, pem, {
99
+ algorithms: [
100
+ "RS256"
101
+ ],
102
+ issuer: this.clerkIssuer
103
+ });
104
+ }
105
+ async fetchJWKS() {
106
+ if (!this.jwksCache) {
107
+ const { data } = await axios.get(this.clerkJWKSUrl);
108
+ this.jwksCache = data.keys;
109
+ }
110
+ return this.jwksCache;
111
+ }
112
+ };
113
+ export {
114
+ AuthClerk
115
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  AuthProviderBase,
3
3
  __name
4
- } from "./chunk-YC7GFXAO.mjs";
4
+ } from "./chunk-KKO5VLFX.mjs";
5
5
 
6
6
  // src/providers/cognito.ts
7
7
  import { CognitoIdentityProviderClient, InitiateAuthCommand } from "@aws-sdk/client-cognito-identity-provider";
package/dist/index.js CHANGED
@@ -280,6 +280,231 @@ var init_cognito = __esm({
280
280
  }
281
281
  });
282
282
 
283
+ // src/providers/auth0.ts
284
+ var auth0_exports = {};
285
+ __export(auth0_exports, {
286
+ AuthAuth0: () => AuthAuth0
287
+ });
288
+ var import_axios2, import_jsonwebtoken2, import_jwk_to_pem2, AuthAuth0;
289
+ var init_auth0 = __esm({
290
+ "src/providers/auth0.ts"() {
291
+ "use strict";
292
+ import_axios2 = __toESM(require("axios"));
293
+ import_jsonwebtoken2 = __toESM(require("jsonwebtoken"));
294
+ import_jwk_to_pem2 = __toESM(require("jwk-to-pem"));
295
+ init_index();
296
+ AuthAuth0 = class extends AuthProviderBase {
297
+ static {
298
+ __name(this, "AuthAuth0");
299
+ }
300
+ domain = "";
301
+ clientId = "";
302
+ clientSecret = "";
303
+ audience = "";
304
+ scopes = "openid profile email offline_access";
305
+ jwksCache = null;
306
+ async init(config) {
307
+ this.domain = config?.domain || process.env.AUTH0_DOMAIN || "";
308
+ this.clientId = config?.clientId || process.env.AUTH0_CLIENT_ID || "";
309
+ this.clientSecret = config?.clientSecret || process.env.AUTH0_CLIENT_SECRET || "";
310
+ this.audience = config?.audience || process.env.AUTH0_AUDIENCE || "";
311
+ this.scopes = config?.scopes || this.scopes;
312
+ if (!this.domain || !this.clientId || !this.audience) {
313
+ throw new Error("Auth0 config missing: domain, clientId, and audience are required");
314
+ }
315
+ }
316
+ async refreshToken(refreshToken) {
317
+ const url = `https://${this.domain}/oauth/token`;
318
+ const payload = {
319
+ grant_type: "refresh_token",
320
+ client_id: this.clientId,
321
+ refresh_token: refreshToken,
322
+ audience: this.audience,
323
+ scope: this.scopes
324
+ };
325
+ if (this.clientSecret) {
326
+ payload.client_secret = this.clientSecret;
327
+ }
328
+ const { data } = await import_axios2.default.post(url, payload, {
329
+ headers: {
330
+ "Content-Type": "application/json"
331
+ }
332
+ });
333
+ return data;
334
+ }
335
+ async verifyToken(token) {
336
+ try {
337
+ await this.verifyJwt(token);
338
+ return true;
339
+ } catch (error) {
340
+ if (error instanceof Error) {
341
+ if (error.message.includes("jwt expired")) throw new Error("Token has expired");
342
+ if (error.message.includes("invalid signature")) throw new Error("Invalid token signature");
343
+ if (error.message.includes("jwt malformed")) throw new Error("Malformed token");
344
+ if (error.message.includes("invalid issuer")) throw new Error("Invalid token issuer");
345
+ throw error;
346
+ }
347
+ return false;
348
+ }
349
+ }
350
+ async getUser(idToken) {
351
+ const decoded = import_jsonwebtoken2.default.decode(idToken);
352
+ if (!decoded) throw new Error("Invalid ID token");
353
+ return {
354
+ sub: decoded.sub,
355
+ email: decoded.email,
356
+ email_verified: decoded.email_verified,
357
+ name: decoded.name,
358
+ attributes: decoded
359
+ };
360
+ }
361
+ async fetchJWKS() {
362
+ if (!this.jwksCache) {
363
+ const jwksUri = `https://${this.domain}/.well-known/jwks.json`;
364
+ const { data } = await import_axios2.default.get(jwksUri);
365
+ this.jwksCache = data.keys;
366
+ }
367
+ return this.jwksCache;
368
+ }
369
+ async verifyJwt(token) {
370
+ const decoded = import_jsonwebtoken2.default.decode(token, {
371
+ complete: true
372
+ });
373
+ if (!decoded) throw new Error("Invalid token");
374
+ const jwks = await this.fetchJWKS();
375
+ const key = jwks.find((k) => k.kid === decoded.header.kid);
376
+ if (!key) throw new Error("Signing key not found in JWKS");
377
+ const pem = (0, import_jwk_to_pem2.default)(key);
378
+ return import_jsonwebtoken2.default.verify(token, pem, {
379
+ algorithms: [
380
+ "RS256"
381
+ ],
382
+ issuer: `https://${this.domain}/`
383
+ });
384
+ }
385
+ };
386
+ }
387
+ });
388
+
389
+ // src/providers/clerk.ts
390
+ var clerk_exports = {};
391
+ __export(clerk_exports, {
392
+ AuthClerk: () => AuthClerk
393
+ });
394
+ var import_axios3, import_jsonwebtoken3, import_jwk_to_pem3, AuthClerk;
395
+ var init_clerk = __esm({
396
+ "src/providers/clerk.ts"() {
397
+ "use strict";
398
+ import_axios3 = __toESM(require("axios"));
399
+ import_jsonwebtoken3 = __toESM(require("jsonwebtoken"));
400
+ import_jwk_to_pem3 = __toESM(require("jwk-to-pem"));
401
+ init_index();
402
+ AuthClerk = class extends AuthProviderBase {
403
+ static {
404
+ __name(this, "AuthClerk");
405
+ }
406
+ clerkFrontendApi = "";
407
+ clerkSecretKey = "";
408
+ clerkJWKSUrl = "";
409
+ clerkIssuer = "";
410
+ jwksCache = null;
411
+ mode = "session";
412
+ oauthTokenUrl = "";
413
+ clientId;
414
+ clientSecret;
415
+ redirectUri;
416
+ /**
417
+ * Initialize Clerk Auth Provider
418
+ */
419
+ async init(config) {
420
+ this.clerkFrontendApi = config?.frontendApi || process.env.CLERK_FRONTEND_API || "";
421
+ this.clerkSecretKey = config?.secretKey || process.env.CLERK_SECRET_KEY || "";
422
+ if (!this.clerkFrontendApi || !this.clerkSecretKey) {
423
+ throw new Error("Missing Clerk configuration: frontendApi and secretKey are required");
424
+ }
425
+ this.clerkIssuer = `https://${this.clerkFrontendApi}`;
426
+ this.clerkJWKSUrl = `${this.clerkIssuer}/.well-known/jwks.json`;
427
+ if (config?.clientId && config?.clientSecret && config?.redirectUri) {
428
+ this.mode = "oauth";
429
+ this.clientId = config.clientId;
430
+ this.clientSecret = config.clientSecret;
431
+ this.redirectUri = config.redirectUri;
432
+ this.oauthTokenUrl = `${this.clerkIssuer}/oauth/token`;
433
+ }
434
+ }
435
+ /**
436
+ * Refresh tokens (OAuth mode only)
437
+ */
438
+ async refreshToken(refreshToken) {
439
+ if (this.mode !== "oauth") {
440
+ throw new Error("Clerk is in Session Mode: refresh tokens are not supported. Enable OAuth mode.");
441
+ }
442
+ const payload = {
443
+ grant_type: "refresh_token",
444
+ refresh_token: refreshToken,
445
+ client_id: this.clientId,
446
+ client_secret: this.clientSecret,
447
+ redirect_uri: this.redirectUri
448
+ };
449
+ const { data } = await import_axios3.default.post(this.oauthTokenUrl, payload, {
450
+ headers: {
451
+ "Content-Type": "application/json"
452
+ }
453
+ });
454
+ return data;
455
+ }
456
+ /**
457
+ * Verify JWT using JWKS
458
+ */
459
+ async verifyToken(token) {
460
+ await this.verifyJwt(token);
461
+ return true;
462
+ }
463
+ /**
464
+ * Extract user data from ID token
465
+ */
466
+ async getUser(idToken) {
467
+ const decoded = import_jsonwebtoken3.default.decode(idToken);
468
+ if (!decoded) throw new Error("Invalid ID token");
469
+ return {
470
+ sub: decoded.sub,
471
+ email: decoded.email,
472
+ email_verified: decoded.email_verified,
473
+ first_name: decoded.given_name,
474
+ last_name: decoded.family_name,
475
+ attributes: decoded
476
+ };
477
+ }
478
+ /**
479
+ * JWT verification using JWKS
480
+ */
481
+ async verifyJwt(token) {
482
+ const decoded = import_jsonwebtoken3.default.decode(token, {
483
+ complete: true
484
+ });
485
+ if (!decoded) throw new Error("Invalid token");
486
+ const jwks = await this.fetchJWKS();
487
+ const key = jwks.find((k) => k.kid === decoded.header.kid);
488
+ if (!key) throw new Error("Signing key not found in JWKS");
489
+ const pem = (0, import_jwk_to_pem3.default)(key);
490
+ return import_jsonwebtoken3.default.verify(token, pem, {
491
+ algorithms: [
492
+ "RS256"
493
+ ],
494
+ issuer: this.clerkIssuer
495
+ });
496
+ }
497
+ async fetchJWKS() {
498
+ if (!this.jwksCache) {
499
+ const { data } = await import_axios3.default.get(this.clerkJWKSUrl);
500
+ this.jwksCache = data.keys;
501
+ }
502
+ return this.jwksCache;
503
+ }
504
+ };
505
+ }
506
+ });
507
+
283
508
  // src/index.ts
284
509
  var index_exports = {};
285
510
  __export(index_exports, {
@@ -325,13 +550,18 @@ var init_index = __esm({
325
550
  await this.providerInstance.init(finalConfig);
326
551
  break;
327
552
  }
328
- // Add more providers here in the future
329
- // case 'clerk': {
330
- // const { AuthClerk } = await import('./providers/clerk');
331
- // this.providerInstance = new AuthClerk();
332
- // await this.providerInstance.init(finalConfig);
333
- // break;
334
- // }
553
+ case "auth0": {
554
+ const { AuthAuth0: AuthAuth02 } = await Promise.resolve().then(() => (init_auth0(), auth0_exports));
555
+ this.providerInstance = new AuthAuth02();
556
+ await this.providerInstance.init(finalConfig);
557
+ break;
558
+ }
559
+ case "clerk": {
560
+ const { AuthClerk: AuthClerk2 } = await Promise.resolve().then(() => (init_clerk(), clerk_exports));
561
+ this.providerInstance = new AuthClerk2();
562
+ await this.providerInstance.init(finalConfig);
563
+ break;
564
+ }
335
565
  default:
336
566
  throw new Error(`Unsupported auth provider: ${this.providerType}. Supported providers: cognito`);
337
567
  }
package/dist/index.mjs CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  AuthenticationError,
6
6
  getAuthProvider,
7
7
  isAuthenticationRequired
8
- } from "./chunk-NALGJYQB.mjs";
8
+ } from "./chunk-KKO5VLFX.mjs";
9
9
  export {
10
10
  AuthProvider,
11
11
  AuthProviderBase,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leanmcp/auth",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Authentication and identity module supporting multiple providers",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -1,193 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
-
4
- // src/index.ts
5
- import "reflect-metadata";
6
-
7
- // src/decorators.ts
8
- import "reflect-metadata";
9
- var AuthenticationError = class extends Error {
10
- static {
11
- __name(this, "AuthenticationError");
12
- }
13
- code;
14
- constructor(message, code) {
15
- super(message), this.code = code;
16
- this.name = "AuthenticationError";
17
- }
18
- };
19
- function Authenticated(authProvider) {
20
- return function(target, propertyKey, descriptor) {
21
- if (!propertyKey && !descriptor) {
22
- Reflect.defineMetadata("auth:provider", authProvider, target);
23
- Reflect.defineMetadata("auth:required", true, target);
24
- const prototype = target.prototype;
25
- const methodNames = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor" && typeof prototype[name] === "function");
26
- for (const methodName of methodNames) {
27
- const originalDescriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
28
- if (originalDescriptor && typeof originalDescriptor.value === "function") {
29
- const originalMethod = originalDescriptor.value;
30
- Reflect.defineMetadata("auth:provider", authProvider, originalMethod);
31
- Reflect.defineMetadata("auth:required", true, originalMethod);
32
- prototype[methodName] = createAuthenticatedMethod(originalMethod, authProvider);
33
- copyMetadata(originalMethod, prototype[methodName]);
34
- }
35
- }
36
- return target;
37
- }
38
- if (descriptor && typeof descriptor.value === "function") {
39
- const originalMethod = descriptor.value;
40
- Reflect.defineMetadata("auth:provider", authProvider, originalMethod);
41
- Reflect.defineMetadata("auth:required", true, originalMethod);
42
- descriptor.value = createAuthenticatedMethod(originalMethod, authProvider);
43
- copyMetadata(originalMethod, descriptor.value);
44
- return descriptor;
45
- }
46
- throw new Error("@Authenticated can only be applied to classes or methods");
47
- };
48
- }
49
- __name(Authenticated, "Authenticated");
50
- function createAuthenticatedMethod(originalMethod, authProvider) {
51
- return async function(...args) {
52
- const firstArg = args[0];
53
- let token;
54
- let cleanedArgs = args;
55
- if (firstArg && typeof firstArg === "object") {
56
- token = firstArg.token;
57
- const { token: _, ...restArgs } = firstArg;
58
- cleanedArgs = [
59
- restArgs,
60
- ...args.slice(1)
61
- ];
62
- }
63
- if (!token) {
64
- throw new AuthenticationError("Authentication required. Please provide a valid token in the request.", "MISSING_TOKEN");
65
- }
66
- try {
67
- const isValid = await authProvider.verifyToken(token);
68
- if (!isValid) {
69
- throw new AuthenticationError("Invalid or expired token. Please authenticate again.", "INVALID_TOKEN");
70
- }
71
- } catch (error) {
72
- if (error instanceof AuthenticationError) {
73
- throw error;
74
- }
75
- throw new AuthenticationError(`Token verification failed: ${error instanceof Error ? error.message : String(error)}`, "VERIFICATION_FAILED");
76
- }
77
- return originalMethod.apply(this, cleanedArgs);
78
- };
79
- }
80
- __name(createAuthenticatedMethod, "createAuthenticatedMethod");
81
- function copyMetadata(source, target) {
82
- const metadataKeys = Reflect.getMetadataKeys(source);
83
- for (const key of metadataKeys) {
84
- const value = Reflect.getMetadata(key, source);
85
- Reflect.defineMetadata(key, value, target);
86
- }
87
- const designKeys = [
88
- "design:type",
89
- "design:paramtypes",
90
- "design:returntype"
91
- ];
92
- for (const key of designKeys) {
93
- const value = Reflect.getMetadata(key, source);
94
- if (value !== void 0) {
95
- Reflect.defineMetadata(key, value, target);
96
- }
97
- }
98
- }
99
- __name(copyMetadata, "copyMetadata");
100
- function isAuthenticationRequired(target) {
101
- return Reflect.getMetadata("auth:required", target) === true;
102
- }
103
- __name(isAuthenticationRequired, "isAuthenticationRequired");
104
- function getAuthProvider(target) {
105
- return Reflect.getMetadata("auth:provider", target);
106
- }
107
- __name(getAuthProvider, "getAuthProvider");
108
-
109
- // src/index.ts
110
- var AuthProviderBase = class {
111
- static {
112
- __name(this, "AuthProviderBase");
113
- }
114
- };
115
- var AuthProvider = class extends AuthProviderBase {
116
- static {
117
- __name(this, "AuthProvider");
118
- }
119
- providerInstance = null;
120
- providerType;
121
- config;
122
- constructor(provider, config) {
123
- super();
124
- this.providerType = provider.toLowerCase();
125
- this.config = config;
126
- }
127
- /**
128
- * Initialize the selected auth provider
129
- */
130
- async init(config) {
131
- const finalConfig = config || this.config;
132
- switch (this.providerType) {
133
- case "cognito": {
134
- const { AuthCognito } = await import("./cognito-GBSAAMZI.mjs");
135
- this.providerInstance = new AuthCognito();
136
- await this.providerInstance.init(finalConfig);
137
- break;
138
- }
139
- // Add more providers here in the future
140
- // case 'clerk': {
141
- // const { AuthClerk } = await import('./providers/clerk');
142
- // this.providerInstance = new AuthClerk();
143
- // await this.providerInstance.init(finalConfig);
144
- // break;
145
- // }
146
- default:
147
- throw new Error(`Unsupported auth provider: ${this.providerType}. Supported providers: cognito`);
148
- }
149
- }
150
- /**
151
- * Refresh an authentication token
152
- */
153
- async refreshToken(refreshToken, username) {
154
- if (!this.providerInstance) {
155
- throw new Error("AuthProvider not initialized. Call init() first.");
156
- }
157
- return this.providerInstance.refreshToken(refreshToken, username);
158
- }
159
- /**
160
- * Verify if a token is valid
161
- */
162
- async verifyToken(token) {
163
- if (!this.providerInstance) {
164
- throw new Error("AuthProvider not initialized. Call init() first.");
165
- }
166
- return this.providerInstance.verifyToken(token);
167
- }
168
- /**
169
- * Get user information from a token
170
- */
171
- async getUser(token) {
172
- if (!this.providerInstance) {
173
- throw new Error("AuthProvider not initialized. Call init() first.");
174
- }
175
- return this.providerInstance.getUser(token);
176
- }
177
- /**
178
- * Get the provider type
179
- */
180
- getProviderType() {
181
- return this.providerType;
182
- }
183
- };
184
-
185
- export {
186
- __name,
187
- AuthenticationError,
188
- Authenticated,
189
- isAuthenticationRequired,
190
- getAuthProvider,
191
- AuthProviderBase,
192
- AuthProvider
193
- };
@@ -1,145 +0,0 @@
1
- import {
2
- AuthProviderBase,
3
- __name
4
- } from "./chunk-NALGJYQB.mjs";
5
-
6
- // src/providers/cognito.ts
7
- import { CognitoIdentityProviderClient, InitiateAuthCommand } from "@aws-sdk/client-cognito-identity-provider";
8
- import { createHmac } from "crypto";
9
- import axios from "axios";
10
- import jwt from "jsonwebtoken";
11
- import jwkToPem from "jwk-to-pem";
12
- var AuthCognito = class extends AuthProviderBase {
13
- static {
14
- __name(this, "AuthCognito");
15
- }
16
- cognito = null;
17
- region = "";
18
- userPoolId = "";
19
- clientId = "";
20
- clientSecret = "";
21
- jwksCache = null;
22
- /**
23
- * Initialize the Cognito client with configuration
24
- */
25
- async init(config) {
26
- this.region = config?.region || process.env.AWS_REGION || "";
27
- this.userPoolId = config?.userPoolId || process.env.COGNITO_USER_POOL_ID || "";
28
- this.clientId = config?.clientId || process.env.COGNITO_CLIENT_ID || "";
29
- this.clientSecret = config?.clientSecret || process.env.COGNITO_CLIENT_SECRET || "";
30
- if (!this.region || !this.userPoolId || !this.clientId) {
31
- throw new Error("Missing required Cognito configuration: region, userPoolId, and clientId are required");
32
- }
33
- this.cognito = new CognitoIdentityProviderClient({
34
- region: this.region
35
- });
36
- }
37
- /**
38
- * Refresh access tokens using a refresh token
39
- */
40
- async refreshToken(refreshToken, username) {
41
- if (!this.cognito) {
42
- throw new Error("CognitoAuth not initialized. Call init() first.");
43
- }
44
- const authParameters = {
45
- REFRESH_TOKEN: refreshToken
46
- };
47
- if (this.clientSecret) {
48
- const usernameForHash = username;
49
- const secretHash = this.calculateSecretHash(usernameForHash);
50
- authParameters.SECRET_HASH = secretHash;
51
- }
52
- const command = new InitiateAuthCommand({
53
- AuthFlow: "REFRESH_TOKEN_AUTH",
54
- ClientId: this.clientId,
55
- AuthParameters: authParameters
56
- });
57
- return await this.cognito.send(command);
58
- }
59
- /**
60
- * Verify a Cognito JWT token using JWKS
61
- */
62
- async verifyToken(token) {
63
- try {
64
- await this.verifyJwt(token);
65
- return true;
66
- } catch (error) {
67
- if (error instanceof Error) {
68
- if (error.message.includes("jwt expired")) {
69
- throw new Error("Token has expired");
70
- } else if (error.message.includes("invalid signature")) {
71
- throw new Error("Invalid token signature");
72
- } else if (error.message.includes("jwt malformed")) {
73
- throw new Error("Malformed token");
74
- } else if (error.message.includes("invalid issuer")) {
75
- throw new Error("Invalid token issuer");
76
- }
77
- throw error;
78
- }
79
- return false;
80
- }
81
- }
82
- /**
83
- * Get user information from an ID token
84
- */
85
- async getUser(idToken) {
86
- const decoded = jwt.decode(idToken);
87
- if (!decoded) {
88
- throw new Error("Invalid ID token");
89
- }
90
- return {
91
- username: decoded["cognito:username"],
92
- email: decoded.email,
93
- email_verified: decoded.email_verified,
94
- sub: decoded.sub,
95
- attributes: decoded
96
- };
97
- }
98
- /**
99
- * Fetch JWKS from Cognito (cached)
100
- */
101
- async fetchJWKS() {
102
- if (!this.jwksCache) {
103
- const jwksUri = `https://cognito-idp.${this.region}.amazonaws.com/${this.userPoolId}/.well-known/jwks.json`;
104
- const { data } = await axios.get(jwksUri);
105
- this.jwksCache = data.keys;
106
- }
107
- return this.jwksCache;
108
- }
109
- /**
110
- * Verify JWT token using JWKS
111
- */
112
- async verifyJwt(token) {
113
- const decoded = jwt.decode(token, {
114
- complete: true
115
- });
116
- if (!decoded) {
117
- throw new Error("Invalid token");
118
- }
119
- const jwks = await this.fetchJWKS();
120
- const key = jwks.find((k) => k.kid === decoded.header.kid);
121
- if (!key) {
122
- throw new Error("Signing key not found in JWKS");
123
- }
124
- const pem = jwkToPem(key);
125
- return jwt.verify(token, pem, {
126
- algorithms: [
127
- "RS256"
128
- ],
129
- issuer: `https://cognito-idp.${this.region}.amazonaws.com/${this.userPoolId}`
130
- });
131
- }
132
- /**
133
- * Calculate SECRET_HASH for Cognito authentication
134
- * SECRET_HASH = Base64(HMAC_SHA256(username + clientId, clientSecret))
135
- */
136
- calculateSecretHash(username) {
137
- const message = username + this.clientId;
138
- const hmac = createHmac("sha256", this.clientSecret);
139
- hmac.update(message);
140
- return hmac.digest("base64");
141
- }
142
- };
143
- export {
144
- AuthCognito
145
- };