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