@leanmcp/auth 0.4.3 → 0.4.5

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.
Files changed (3) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +400 -396
  3. package/package.json +121 -121
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 LeanMCP Contributors
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.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 LeanMCP Contributors
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 CHANGED
@@ -1,396 +1,400 @@
1
- <p align="center">
2
- <img
3
- src="https://raw.githubusercontent.com/LeanMCP/leanmcp-sdk/refs/heads/main/assets/logo.png"
4
- alt="LeanMCP Logo"
5
- width="400"
6
- />
7
- </p>
8
-
9
- <p align="center">
10
- <strong>@leanmcp/auth</strong><br/>
11
- Token-based authentication decorators and multi-provider support for MCP tools.
12
- </p>
13
-
14
- <p align="center">
15
- <a href="https://www.npmjs.com/package/@leanmcp/auth">
16
- <img src="https://img.shields.io/npm/v/@leanmcp/auth" alt="npm version" />
17
- </a>
18
- <a href="https://www.npmjs.com/package/@leanmcp/auth">
19
- <img src="https://img.shields.io/npm/dm/@leanmcp/auth" alt="npm downloads" />
20
- </a>
21
- <a href="https://docs.leanmcp.com/sdk/auth">
22
- <img src="https://img.shields.io/badge/Docs-leanmcp-0A66C2?" />
23
- </a>
24
- <a href="https://discord.com/invite/DsRcA3GwPy">
25
- <img src="https://img.shields.io/badge/Discord-Join-5865F2?logo=discord&logoColor=white" />
26
- </a>
27
- <a href="https://x.com/LeanMcp">
28
- <img src="https://img.shields.io/badge/@LeanMCP-f5f5f5?logo=x&logoColor=000000" />
29
- </a>
30
- </p>
31
-
32
- ## Features
33
-
34
- - **@Authenticated Decorator** — Protect tools, prompts, and resources with a simple decorator
35
- - **Multi-Provider Support** — AWS Cognito, Clerk, Auth0, and LeanMCP providers
36
- - **Automatic authUser** — Decoded user info injected as global `authUser` variable
37
- - **Concurrency Safe** — Uses AsyncLocalStorage for request-isolated context
38
- - **Method or Class-Level** — Apply to individual methods or entire services
39
- - **OAuth & Session Modes** — Support for both session-based and OAuth refresh token flows
40
-
41
- ## Installation
42
-
43
- ```bash
44
- npm install @leanmcp/auth @leanmcp/core
45
- ```
46
-
47
- ### Provider Dependencies
48
-
49
- **AWS Cognito:**
50
- ```bash
51
- npm install @aws-sdk/client-cognito-identity-provider axios jsonwebtoken jwk-to-pem
52
- ```
53
-
54
- **Clerk:**
55
- ```bash
56
- npm install axios jsonwebtoken jwk-to-pem
57
- ```
58
-
59
- **Auth0:**
60
- ```bash
61
- npm install axios jsonwebtoken jwk-to-pem
62
- ```
63
-
64
- ## Quick Start
65
-
66
- ### 1. Initialize Auth Provider
67
-
68
- ```typescript
69
- import { AuthProvider } from "@leanmcp/auth";
70
-
71
- const authProvider = new AuthProvider('cognito', {
72
- region: 'us-east-1',
73
- userPoolId: 'us-east-1_XXXXXXXXX',
74
- clientId: 'your-client-id'
75
- });
76
-
77
- await authProvider.init();
78
- ```
79
-
80
- ### 2. Protect Methods with @Authenticated
81
-
82
- ```typescript
83
- import { Tool } from "@leanmcp/core";
84
- import { Authenticated } from "@leanmcp/auth";
85
-
86
- export class SentimentService {
87
- @Tool({ description: 'Analyze sentiment (requires auth)' })
88
- @Authenticated(authProvider)
89
- async analyzeSentiment(input: { text: string }) {
90
- // authUser is automatically available with user info
91
- console.log('User ID:', authUser.sub);
92
- console.log('Email:', authUser.email);
93
-
94
- return {
95
- sentiment: 'positive',
96
- score: 0.8,
97
- analyzedBy: authUser.sub
98
- };
99
- }
100
-
101
- // Public method - no authentication
102
- @Tool({ description: 'Get categories (public)' })
103
- async getCategories() {
104
- return { categories: ['positive', 'negative', 'neutral'] };
105
- }
106
- }
107
- ```
108
-
109
- ### 3. Protect Entire Service
110
-
111
- ```typescript
112
- // All methods in this class require authentication
113
- @Authenticated(authProvider)
114
- export class SecureService {
115
- @Tool({ description: 'Protected tool' })
116
- async protectedTool(input: { data: string }) {
117
- // authUser is available in all methods
118
- return { data: input.data, userId: authUser.sub };
119
- }
120
- }
121
- ```
122
-
123
- ---
124
-
125
- ## The authUser Variable
126
-
127
- When using `@Authenticated`, a global `authUser` variable is automatically injected containing the decoded JWT payload:
128
-
129
- ```typescript
130
- @Tool({ description: 'Create post' })
131
- @Authenticated(authProvider)
132
- async createPost(input: { title: string, content: string }) {
133
- return {
134
- id: generateId(),
135
- title: input.title,
136
- content: input.content,
137
- authorId: authUser.sub,
138
- authorEmail: authUser.email
139
- };
140
- }
141
- ```
142
-
143
- ### Provider-Specific User Data
144
-
145
- **AWS Cognito:**
146
- ```typescript
147
- {
148
- sub: 'user-uuid',
149
- email: 'user@example.com',
150
- email_verified: true,
151
- 'cognito:username': 'username',
152
- 'cognito:groups': ['admin', 'users']
153
- }
154
- ```
155
-
156
- **Clerk:**
157
- ```typescript
158
- {
159
- sub: 'user_2abc123xyz',
160
- userId: 'user_2abc123xyz',
161
- email: 'user@example.com',
162
- firstName: 'John',
163
- lastName: 'Doe',
164
- imageUrl: 'https://img.clerk.com/...'
165
- }
166
- ```
167
-
168
- **Auth0:**
169
- ```typescript
170
- {
171
- sub: 'auth0|507f1f77bcf86cd799439011',
172
- email: 'user@example.com',
173
- email_verified: true,
174
- name: 'John Doe',
175
- picture: 'https://s.gravatar.com/avatar/...'
176
- }
177
- ```
178
-
179
- ### Controlling User Fetch
180
-
181
- ```typescript
182
- // Fetch user info (default)
183
- @Authenticated(authProvider, { getUser: true })
184
- async withUserInfo(input: any) {
185
- console.log(authUser); // User data available
186
- }
187
-
188
- // Only verify token, skip user fetch (faster)
189
- @Authenticated(authProvider, { getUser: false })
190
- async tokenOnlyValidation(input: any) {
191
- // authUser is undefined
192
- }
193
- ```
194
-
195
- ---
196
-
197
- ## Supported Providers
198
-
199
- ### AWS Cognito
200
-
201
- ```typescript
202
- const authProvider = new AuthProvider('cognito', {
203
- region: 'us-east-1',
204
- userPoolId: 'us-east-1_XXXXXXXXX',
205
- clientId: 'your-client-id'
206
- });
207
- await authProvider.init();
208
- ```
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
- ```typescript
220
- // Session Mode (default)
221
- const authProvider = new AuthProvider('clerk', {
222
- frontendApi: 'your-frontend-api.clerk.accounts.dev',
223
- secretKey: 'sk_test_...'
224
- });
225
-
226
- // OAuth Mode (with refresh tokens)
227
- const authProvider = new AuthProvider('clerk', {
228
- frontendApi: 'your-frontend-api.clerk.accounts.dev',
229
- secretKey: 'sk_test_...',
230
- clientId: 'your-oauth-client-id',
231
- clientSecret: 'your-oauth-client-secret',
232
- redirectUri: 'https://yourapp.com/callback'
233
- });
234
-
235
- await authProvider.init();
236
- ```
237
-
238
- ### Auth0
239
-
240
- ```typescript
241
- const authProvider = new AuthProvider('auth0', {
242
- domain: 'your-tenant.auth0.com',
243
- clientId: 'your-client-id',
244
- clientSecret: 'your-client-secret',
245
- audience: 'https://your-api-identifier'
246
- });
247
- await authProvider.init();
248
- ```
249
-
250
- ### LeanMCP
251
-
252
- For LeanMCP platform deployments with user secrets support:
253
-
254
- ```typescript
255
- const authProvider = new AuthProvider('leanmcp', {
256
- apiKey: 'your-leanmcp-api-key'
257
- });
258
- await authProvider.init();
259
- ```
260
-
261
- ---
262
-
263
- ## Client Usage
264
-
265
- Authentication tokens are passed via the `_meta` field following MCP protocol standards:
266
-
267
- ```typescript
268
- await mcpClient.callTool({
269
- name: "analyzeSentiment",
270
- arguments: { text: "Hello world" },
271
- _meta: {
272
- authorization: {
273
- type: "bearer",
274
- token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
275
- }
276
- }
277
- });
278
- ```
279
-
280
- ---
281
-
282
- ## Error Handling
283
-
284
- ```typescript
285
- import { AuthenticationError } from "@leanmcp/auth";
286
-
287
- try {
288
- await service.protectedMethod({ text: "test" });
289
- } catch (error) {
290
- if (error instanceof AuthenticationError) {
291
- switch (error.code) {
292
- case 'MISSING_TOKEN':
293
- console.log('No token provided');
294
- break;
295
- case 'INVALID_TOKEN':
296
- console.log('Token is invalid or expired');
297
- break;
298
- case 'VERIFICATION_FAILED':
299
- console.log('Verification failed:', error.message);
300
- break;
301
- }
302
- }
303
- }
304
- ```
305
-
306
- ---
307
-
308
- ## API Reference
309
-
310
- ### AuthProvider
311
-
312
- ```typescript
313
- class AuthProvider {
314
- constructor(provider: string, config: any);
315
- async init(config?: any): Promise<void>;
316
- async verifyToken(token: string): Promise<boolean>;
317
- async refreshToken(refreshToken: string): Promise<any>;
318
- async getUser(token: string): Promise<any>;
319
- getProviderType(): string;
320
- }
321
- ```
322
-
323
- ### @Authenticated Decorator
324
-
325
- ```typescript
326
- function Authenticated(
327
- authProvider: AuthProvider,
328
- options?: AuthenticatedOptions
329
- ): ClassDecorator | MethodDecorator;
330
-
331
- interface AuthenticatedOptions {
332
- getUser?: boolean; // Default: true
333
- projectId?: string; // For LeanMCP user secrets
334
- }
335
- ```
336
-
337
- ### AuthenticationError
338
-
339
- ```typescript
340
- class AuthenticationError extends Error {
341
- code: 'MISSING_TOKEN' | 'INVALID_TOKEN' | 'VERIFICATION_FAILED';
342
- constructor(message: string, code: string);
343
- }
344
- ```
345
-
346
- ### Helper Functions
347
-
348
- ```typescript
349
- // Check if authentication is required
350
- function isAuthenticationRequired(target: any): boolean;
351
-
352
- // Get auth provider for method/class
353
- function getAuthProvider(target: any): AuthProviderBase | undefined;
354
-
355
- // Get current authenticated user
356
- function getAuthUser(): any;
357
- ```
358
-
359
- ---
360
-
361
- ## Best Practices
362
-
363
- ### Security
364
- - Always use HTTPS in production
365
- - Store tokens securely (keychain, encrypted storage)
366
- - Implement token refresh before expiration
367
- - Add rate limiting to protect against brute force
368
-
369
- ### Configuration
370
- - Use environment variables for credentials
371
- - Never hardcode secrets in code
372
- - Use `_meta` for auth, not business arguments
373
-
374
- ### Performance
375
- - Use `getUser: false` when you only need token validation
376
- - JWKS keys are cached automatically for performance
377
-
378
- ---
379
-
380
- ## Documentation
381
-
382
- - [Full Documentation](https://docs.leanmcp.com/sdk/auth)
383
-
384
- ## Related Packages
385
-
386
- - [@leanmcp/core](https://www.npmjs.com/package/@leanmcp/core) — Core decorators and server functionality
387
- - [@leanmcp/env-injection](https://www.npmjs.com/package/@leanmcp/env-injection) — Environment variable injection for user secrets
388
-
389
- ## Links
390
-
391
- - [GitHub Repository](https://github.com/LeanMCP/leanmcp-sdk)
392
- - [NPM Package](https://www.npmjs.com/package/@leanmcp/auth)
393
-
394
- ## License
395
-
396
- MIT
1
+ <p align="center">
2
+ <img
3
+ src="https://raw.githubusercontent.com/LeanMCP/leanmcp-sdk/refs/heads/main/assets/logo.png"
4
+ alt="LeanMCP Logo"
5
+ width="400"
6
+ />
7
+ </p>
8
+
9
+ <p align="center">
10
+ <strong>@leanmcp/auth</strong><br/>
11
+ Token-based authentication decorators and multi-provider support for MCP tools.
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="https://www.npmjs.com/package/@leanmcp/auth">
16
+ <img src="https://img.shields.io/npm/v/@leanmcp/auth" alt="npm version" />
17
+ </a>
18
+ <a href="https://www.npmjs.com/package/@leanmcp/auth">
19
+ <img src="https://img.shields.io/npm/dm/@leanmcp/auth" alt="npm downloads" />
20
+ </a>
21
+ <a href="https://docs.leanmcp.com/sdk/auth">
22
+ <img src="https://img.shields.io/badge/Docs-leanmcp-0A66C2?" />
23
+ </a>
24
+ <a href="https://discord.com/invite/DsRcA3GwPy">
25
+ <img src="https://img.shields.io/badge/Discord-Join-5865F2?logo=discord&logoColor=white" />
26
+ </a>
27
+ <a href="https://x.com/LeanMcp">
28
+ <img src="https://img.shields.io/badge/@LeanMCP-f5f5f5?logo=x&logoColor=000000" />
29
+ </a>
30
+ <a href="https://leanmcp.com/">
31
+ <img src="https://img.shields.io/badge/Website-leanmcp-0A66C2?" />
32
+ </a>
33
+ <a href="https://deepwiki.com/LeanMCP/leanmcp-sdk"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
34
+ </p>
35
+
36
+ ## Features
37
+
38
+ - **@Authenticated Decorator** — Protect tools, prompts, and resources with a simple decorator
39
+ - **Multi-Provider Support** — AWS Cognito, Clerk, Auth0, and LeanMCP providers
40
+ - **Automatic authUser** — Decoded user info injected as global `authUser` variable
41
+ - **Concurrency Safe** — Uses AsyncLocalStorage for request-isolated context
42
+ - **Method or Class-Level** — Apply to individual methods or entire services
43
+ - **OAuth & Session Modes** — Support for both session-based and OAuth refresh token flows
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ npm install @leanmcp/auth @leanmcp/core
49
+ ```
50
+
51
+ ### Provider Dependencies
52
+
53
+ **AWS Cognito:**
54
+ ```bash
55
+ npm install @aws-sdk/client-cognito-identity-provider axios jsonwebtoken jwk-to-pem
56
+ ```
57
+
58
+ **Clerk:**
59
+ ```bash
60
+ npm install axios jsonwebtoken jwk-to-pem
61
+ ```
62
+
63
+ **Auth0:**
64
+ ```bash
65
+ npm install axios jsonwebtoken jwk-to-pem
66
+ ```
67
+
68
+ ## Quick Start
69
+
70
+ ### 1. Initialize Auth Provider
71
+
72
+ ```typescript
73
+ import { AuthProvider } from "@leanmcp/auth";
74
+
75
+ const authProvider = new AuthProvider('cognito', {
76
+ region: 'us-east-1',
77
+ userPoolId: 'us-east-1_XXXXXXXXX',
78
+ clientId: 'your-client-id'
79
+ });
80
+
81
+ await authProvider.init();
82
+ ```
83
+
84
+ ### 2. Protect Methods with @Authenticated
85
+
86
+ ```typescript
87
+ import { Tool } from "@leanmcp/core";
88
+ import { Authenticated } from "@leanmcp/auth";
89
+
90
+ export class SentimentService {
91
+ @Tool({ description: 'Analyze sentiment (requires auth)' })
92
+ @Authenticated(authProvider)
93
+ async analyzeSentiment(input: { text: string }) {
94
+ // authUser is automatically available with user info
95
+ console.log('User ID:', authUser.sub);
96
+ console.log('Email:', authUser.email);
97
+
98
+ return {
99
+ sentiment: 'positive',
100
+ score: 0.8,
101
+ analyzedBy: authUser.sub
102
+ };
103
+ }
104
+
105
+ // Public method - no authentication
106
+ @Tool({ description: 'Get categories (public)' })
107
+ async getCategories() {
108
+ return { categories: ['positive', 'negative', 'neutral'] };
109
+ }
110
+ }
111
+ ```
112
+
113
+ ### 3. Protect Entire Service
114
+
115
+ ```typescript
116
+ // All methods in this class require authentication
117
+ @Authenticated(authProvider)
118
+ export class SecureService {
119
+ @Tool({ description: 'Protected tool' })
120
+ async protectedTool(input: { data: string }) {
121
+ // authUser is available in all methods
122
+ return { data: input.data, userId: authUser.sub };
123
+ }
124
+ }
125
+ ```
126
+
127
+ ---
128
+
129
+ ## The authUser Variable
130
+
131
+ When using `@Authenticated`, a global `authUser` variable is automatically injected containing the decoded JWT payload:
132
+
133
+ ```typescript
134
+ @Tool({ description: 'Create post' })
135
+ @Authenticated(authProvider)
136
+ async createPost(input: { title: string, content: string }) {
137
+ return {
138
+ id: generateId(),
139
+ title: input.title,
140
+ content: input.content,
141
+ authorId: authUser.sub,
142
+ authorEmail: authUser.email
143
+ };
144
+ }
145
+ ```
146
+
147
+ ### Provider-Specific User Data
148
+
149
+ **AWS Cognito:**
150
+ ```typescript
151
+ {
152
+ sub: 'user-uuid',
153
+ email: 'user@example.com',
154
+ email_verified: true,
155
+ 'cognito:username': 'username',
156
+ 'cognito:groups': ['admin', 'users']
157
+ }
158
+ ```
159
+
160
+ **Clerk:**
161
+ ```typescript
162
+ {
163
+ sub: 'user_2abc123xyz',
164
+ userId: 'user_2abc123xyz',
165
+ email: 'user@example.com',
166
+ firstName: 'John',
167
+ lastName: 'Doe',
168
+ imageUrl: 'https://img.clerk.com/...'
169
+ }
170
+ ```
171
+
172
+ **Auth0:**
173
+ ```typescript
174
+ {
175
+ sub: 'auth0|507f1f77bcf86cd799439011',
176
+ email: 'user@example.com',
177
+ email_verified: true,
178
+ name: 'John Doe',
179
+ picture: 'https://s.gravatar.com/avatar/...'
180
+ }
181
+ ```
182
+
183
+ ### Controlling User Fetch
184
+
185
+ ```typescript
186
+ // Fetch user info (default)
187
+ @Authenticated(authProvider, { getUser: true })
188
+ async withUserInfo(input: any) {
189
+ console.log(authUser); // User data available
190
+ }
191
+
192
+ // Only verify token, skip user fetch (faster)
193
+ @Authenticated(authProvider, { getUser: false })
194
+ async tokenOnlyValidation(input: any) {
195
+ // authUser is undefined
196
+ }
197
+ ```
198
+
199
+ ---
200
+
201
+ ## Supported Providers
202
+
203
+ ### AWS Cognito
204
+
205
+ ```typescript
206
+ const authProvider = new AuthProvider('cognito', {
207
+ region: 'us-east-1',
208
+ userPoolId: 'us-east-1_XXXXXXXXX',
209
+ clientId: 'your-client-id'
210
+ });
211
+ await authProvider.init();
212
+ ```
213
+
214
+ **Environment Variables:**
215
+ ```bash
216
+ AWS_REGION=us-east-1
217
+ COGNITO_USER_POOL_ID=us-east-1_XXXXXXXXX
218
+ COGNITO_CLIENT_ID=your-client-id
219
+ ```
220
+
221
+ ### Clerk
222
+
223
+ ```typescript
224
+ // Session Mode (default)
225
+ const authProvider = new AuthProvider('clerk', {
226
+ frontendApi: 'your-frontend-api.clerk.accounts.dev',
227
+ secretKey: 'sk_test_...'
228
+ });
229
+
230
+ // OAuth Mode (with refresh tokens)
231
+ const authProvider = new AuthProvider('clerk', {
232
+ frontendApi: 'your-frontend-api.clerk.accounts.dev',
233
+ secretKey: 'sk_test_...',
234
+ clientId: 'your-oauth-client-id',
235
+ clientSecret: 'your-oauth-client-secret',
236
+ redirectUri: 'https://yourapp.com/callback'
237
+ });
238
+
239
+ await authProvider.init();
240
+ ```
241
+
242
+ ### Auth0
243
+
244
+ ```typescript
245
+ const authProvider = new AuthProvider('auth0', {
246
+ domain: 'your-tenant.auth0.com',
247
+ clientId: 'your-client-id',
248
+ clientSecret: 'your-client-secret',
249
+ audience: 'https://your-api-identifier'
250
+ });
251
+ await authProvider.init();
252
+ ```
253
+
254
+ ### LeanMCP
255
+
256
+ For LeanMCP platform deployments with user secrets support:
257
+
258
+ ```typescript
259
+ const authProvider = new AuthProvider('leanmcp', {
260
+ apiKey: 'your-leanmcp-api-key'
261
+ });
262
+ await authProvider.init();
263
+ ```
264
+
265
+ ---
266
+
267
+ ## Client Usage
268
+
269
+ Authentication tokens are passed via the `_meta` field following MCP protocol standards:
270
+
271
+ ```typescript
272
+ await mcpClient.callTool({
273
+ name: "analyzeSentiment",
274
+ arguments: { text: "Hello world" },
275
+ _meta: {
276
+ authorization: {
277
+ type: "bearer",
278
+ token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
279
+ }
280
+ }
281
+ });
282
+ ```
283
+
284
+ ---
285
+
286
+ ## Error Handling
287
+
288
+ ```typescript
289
+ import { AuthenticationError } from "@leanmcp/auth";
290
+
291
+ try {
292
+ await service.protectedMethod({ text: "test" });
293
+ } catch (error) {
294
+ if (error instanceof AuthenticationError) {
295
+ switch (error.code) {
296
+ case 'MISSING_TOKEN':
297
+ console.log('No token provided');
298
+ break;
299
+ case 'INVALID_TOKEN':
300
+ console.log('Token is invalid or expired');
301
+ break;
302
+ case 'VERIFICATION_FAILED':
303
+ console.log('Verification failed:', error.message);
304
+ break;
305
+ }
306
+ }
307
+ }
308
+ ```
309
+
310
+ ---
311
+
312
+ ## API Reference
313
+
314
+ ### AuthProvider
315
+
316
+ ```typescript
317
+ class AuthProvider {
318
+ constructor(provider: string, config: any);
319
+ async init(config?: any): Promise<void>;
320
+ async verifyToken(token: string): Promise<boolean>;
321
+ async refreshToken(refreshToken: string): Promise<any>;
322
+ async getUser(token: string): Promise<any>;
323
+ getProviderType(): string;
324
+ }
325
+ ```
326
+
327
+ ### @Authenticated Decorator
328
+
329
+ ```typescript
330
+ function Authenticated(
331
+ authProvider: AuthProvider,
332
+ options?: AuthenticatedOptions
333
+ ): ClassDecorator | MethodDecorator;
334
+
335
+ interface AuthenticatedOptions {
336
+ getUser?: boolean; // Default: true
337
+ projectId?: string; // For LeanMCP user secrets
338
+ }
339
+ ```
340
+
341
+ ### AuthenticationError
342
+
343
+ ```typescript
344
+ class AuthenticationError extends Error {
345
+ code: 'MISSING_TOKEN' | 'INVALID_TOKEN' | 'VERIFICATION_FAILED';
346
+ constructor(message: string, code: string);
347
+ }
348
+ ```
349
+
350
+ ### Helper Functions
351
+
352
+ ```typescript
353
+ // Check if authentication is required
354
+ function isAuthenticationRequired(target: any): boolean;
355
+
356
+ // Get auth provider for method/class
357
+ function getAuthProvider(target: any): AuthProviderBase | undefined;
358
+
359
+ // Get current authenticated user
360
+ function getAuthUser(): any;
361
+ ```
362
+
363
+ ---
364
+
365
+ ## Best Practices
366
+
367
+ ### Security
368
+ - Always use HTTPS in production
369
+ - Store tokens securely (keychain, encrypted storage)
370
+ - Implement token refresh before expiration
371
+ - Add rate limiting to protect against brute force
372
+
373
+ ### Configuration
374
+ - Use environment variables for credentials
375
+ - Never hardcode secrets in code
376
+ - Use `_meta` for auth, not business arguments
377
+
378
+ ### Performance
379
+ - Use `getUser: false` when you only need token validation
380
+ - JWKS keys are cached automatically for performance
381
+
382
+ ---
383
+
384
+ ## Documentation
385
+
386
+ - [Full Documentation](https://docs.leanmcp.com/sdk/auth)
387
+
388
+ ## Related Packages
389
+
390
+ - [@leanmcp/core](https://www.npmjs.com/package/@leanmcp/core) — Core decorators and server functionality
391
+ - [@leanmcp/env-injection](https://www.npmjs.com/package/@leanmcp/env-injection) — Environment variable injection for user secrets
392
+
393
+ ## Links
394
+
395
+ - [GitHub Repository](https://github.com/LeanMCP/leanmcp-sdk)
396
+ - [NPM Package](https://www.npmjs.com/package/@leanmcp/auth)
397
+
398
+ ## License
399
+
400
+ MIT
package/package.json CHANGED
@@ -1,121 +1,121 @@
1
- {
2
- "name": "@leanmcp/auth",
3
- "version": "0.4.3",
4
- "description": "Authentication and identity module with OAuth 2.1 client, token storage, and multiple providers",
5
- "main": "dist/index.js",
6
- "module": "dist/index.mjs",
7
- "types": "dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "require": "./dist/index.js",
12
- "import": "./dist/index.mjs"
13
- },
14
- "./client": {
15
- "types": "./dist/client/index.d.ts",
16
- "require": "./dist/client/index.js",
17
- "import": "./dist/client/index.mjs"
18
- },
19
- "./storage": {
20
- "types": "./dist/storage/index.d.ts",
21
- "require": "./dist/storage/index.js",
22
- "import": "./dist/storage/index.mjs"
23
- },
24
- "./proxy": {
25
- "types": "./dist/proxy/index.d.ts",
26
- "require": "./dist/proxy/index.js",
27
- "import": "./dist/proxy/index.mjs"
28
- },
29
- "./server": {
30
- "types": "./dist/server/index.d.ts",
31
- "require": "./dist/server/index.js",
32
- "import": "./dist/server/index.mjs"
33
- }
34
- },
35
- "files": [
36
- "dist",
37
- "README.md",
38
- "LICENSE"
39
- ],
40
- "scripts": {
41
- "build": "tsup src/index.ts src/client/index.ts src/storage/index.ts src/proxy/index.ts src/server/index.ts --format esm,cjs --dts",
42
- "dev": "tsup src/index.ts src/client/index.ts src/storage/index.ts src/proxy/index.ts src/server/index.ts --format esm,cjs --dts --watch",
43
- "test": "jest --passWithNoTests",
44
- "test:watch": "jest --watch"
45
- },
46
- "dependencies": {
47
- "@leanmcp/core": "^0.3.0",
48
- "reflect-metadata": "^0.2.1"
49
- },
50
- "devDependencies": {
51
- "@leanmcp/env-injection": "^0.1.0",
52
- "@types/jest": "^29.5.0",
53
- "@types/jsonwebtoken": "^9.0.10",
54
- "@types/jwk-to-pem": "^2.0.3",
55
- "@types/node": "^20.0.0",
56
- "dotenv": "^17.2.3",
57
- "jest": "^29.7.0",
58
- "ts-jest": "^29.1.0",
59
- "express": "^5.0.0"
60
- },
61
- "peerDependencies": {
62
- "@aws-sdk/client-cognito-identity-provider": "^3.0.0",
63
- "@leanmcp/env-injection": "^0.1.0",
64
- "axios": "^1.0.0",
65
- "jsonwebtoken": "^9.0.0",
66
- "jwk-to-pem": "^2.0.0",
67
- "keytar": "^7.0.0",
68
- "open": "^10.0.0",
69
- "express": "^5.0.0"
70
- },
71
- "peerDependenciesMeta": {
72
- "@aws-sdk/client-cognito-identity-provider": {
73
- "optional": true
74
- },
75
- "@leanmcp/env-injection": {
76
- "optional": true
77
- },
78
- "axios": {
79
- "optional": true
80
- },
81
- "jsonwebtoken": {
82
- "optional": true
83
- },
84
- "jwk-to-pem": {
85
- "optional": true
86
- },
87
- "keytar": {
88
- "optional": true
89
- },
90
- "open": {
91
- "optional": true
92
- }
93
- },
94
- "repository": {
95
- "type": "git",
96
- "url": "git+https://github.com/LeanMCP/leanmcp-sdk.git",
97
- "directory": "packages/auth"
98
- },
99
- "homepage": "https://github.com/LeanMCP/leanmcp-sdk#readme",
100
- "bugs": {
101
- "url": "https://github.com/LeanMCP/leanmcp-sdk/issues"
102
- },
103
- "keywords": [
104
- "mcp",
105
- "model-context-protocol",
106
- "typescript",
107
- "decorators",
108
- "authentication",
109
- "auth",
110
- "cognito",
111
- "jwt",
112
- "oauth",
113
- "pkce",
114
- "oauth2"
115
- ],
116
- "author": "LeanMCP <admin@leanmcp.com>",
117
- "license": "MIT",
118
- "publishConfig": {
119
- "access": "public"
120
- }
121
- }
1
+ {
2
+ "name": "@leanmcp/auth",
3
+ "version": "0.4.5",
4
+ "description": "Authentication and identity module with OAuth 2.1 client, token storage, and multiple providers",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "require": "./dist/index.js",
12
+ "import": "./dist/index.mjs"
13
+ },
14
+ "./client": {
15
+ "types": "./dist/client/index.d.ts",
16
+ "require": "./dist/client/index.js",
17
+ "import": "./dist/client/index.mjs"
18
+ },
19
+ "./storage": {
20
+ "types": "./dist/storage/index.d.ts",
21
+ "require": "./dist/storage/index.js",
22
+ "import": "./dist/storage/index.mjs"
23
+ },
24
+ "./proxy": {
25
+ "types": "./dist/proxy/index.d.ts",
26
+ "require": "./dist/proxy/index.js",
27
+ "import": "./dist/proxy/index.mjs"
28
+ },
29
+ "./server": {
30
+ "types": "./dist/server/index.d.ts",
31
+ "require": "./dist/server/index.js",
32
+ "import": "./dist/server/index.mjs"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "README.md",
38
+ "LICENSE"
39
+ ],
40
+ "scripts": {
41
+ "build": "tsup src/index.ts src/client/index.ts src/storage/index.ts src/proxy/index.ts src/server/index.ts --format esm,cjs --dts",
42
+ "dev": "tsup src/index.ts src/client/index.ts src/storage/index.ts src/proxy/index.ts src/server/index.ts --format esm,cjs --dts --watch",
43
+ "test": "jest --passWithNoTests",
44
+ "test:watch": "jest --watch"
45
+ },
46
+ "dependencies": {
47
+ "@leanmcp/core": "^0.3.0",
48
+ "reflect-metadata": "^0.2.1"
49
+ },
50
+ "devDependencies": {
51
+ "@leanmcp/env-injection": "^0.1.0",
52
+ "@types/jest": "^29.5.0",
53
+ "@types/jsonwebtoken": "^9.0.10",
54
+ "@types/jwk-to-pem": "^2.0.3",
55
+ "@types/node": "^20.0.0",
56
+ "dotenv": "^17.2.3",
57
+ "jest": "^29.7.0",
58
+ "ts-jest": "^29.1.0",
59
+ "express": "^5.0.0"
60
+ },
61
+ "peerDependencies": {
62
+ "@aws-sdk/client-cognito-identity-provider": "^3.0.0",
63
+ "@leanmcp/env-injection": "^0.1.0",
64
+ "axios": "^1.0.0",
65
+ "jsonwebtoken": "^9.0.0",
66
+ "jwk-to-pem": "^2.0.0",
67
+ "keytar": "^7.0.0",
68
+ "open": "^10.0.0",
69
+ "express": "^5.0.0"
70
+ },
71
+ "peerDependenciesMeta": {
72
+ "@aws-sdk/client-cognito-identity-provider": {
73
+ "optional": true
74
+ },
75
+ "@leanmcp/env-injection": {
76
+ "optional": true
77
+ },
78
+ "axios": {
79
+ "optional": true
80
+ },
81
+ "jsonwebtoken": {
82
+ "optional": true
83
+ },
84
+ "jwk-to-pem": {
85
+ "optional": true
86
+ },
87
+ "keytar": {
88
+ "optional": true
89
+ },
90
+ "open": {
91
+ "optional": true
92
+ }
93
+ },
94
+ "repository": {
95
+ "type": "git",
96
+ "url": "git+https://github.com/LeanMCP/leanmcp-sdk.git",
97
+ "directory": "packages/auth"
98
+ },
99
+ "homepage": "https://github.com/LeanMCP/leanmcp-sdk#readme",
100
+ "bugs": {
101
+ "url": "https://github.com/LeanMCP/leanmcp-sdk/issues"
102
+ },
103
+ "keywords": [
104
+ "mcp",
105
+ "model-context-protocol",
106
+ "typescript",
107
+ "decorators",
108
+ "authentication",
109
+ "auth",
110
+ "cognito",
111
+ "jwt",
112
+ "oauth",
113
+ "pkce",
114
+ "oauth2"
115
+ ],
116
+ "author": "LeanMCP <admin@leanmcp.com>",
117
+ "license": "MIT",
118
+ "publishConfig": {
119
+ "access": "public"
120
+ }
121
+ }