@leanmcp/auth 0.3.1 → 0.3.2
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/dist/{auth0-54GZT2EI.mjs → auth0-DMNC3QWJ.mjs} +1 -1
- package/dist/{chunk-EVD2TRPR.mjs → chunk-ESHQ6BRM.mjs} +47 -18
- package/dist/{clerk-FR7ITM33.mjs → clerk-7PVVTTC7.mjs} +1 -1
- package/dist/{cognito-I6V5YNYM.mjs → cognito-5Q5HGYMA.mjs} +1 -1
- package/dist/index.d.mts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +186 -15
- package/dist/index.mjs +1 -1
- package/dist/leanmcp-X6BD6HOJ.mjs +138 -0
- package/package.json +6 -2
|
@@ -86,29 +86,39 @@ function createAuthenticatedMethod(originalMethod, authProvider, options) {
|
|
|
86
86
|
}
|
|
87
87
|
throw new AuthenticationError(`Token verification failed: ${error instanceof Error ? error.message : String(error)}`, "VERIFICATION_FAILED");
|
|
88
88
|
}
|
|
89
|
+
let user = void 0;
|
|
89
90
|
if (options.getUser !== false) {
|
|
90
91
|
try {
|
|
91
|
-
|
|
92
|
-
return await authUserStorage.run(user, async () => {
|
|
93
|
-
return await originalMethod.apply(this, [
|
|
94
|
-
args
|
|
95
|
-
]);
|
|
96
|
-
});
|
|
92
|
+
user = await authProvider.getUser(token);
|
|
97
93
|
} catch (error) {
|
|
98
94
|
console.warn("Failed to fetch user information:", error);
|
|
99
|
-
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
let userSecrets = {};
|
|
98
|
+
if (options.projectId) {
|
|
99
|
+
try {
|
|
100
|
+
if ("getUserSecrets" in authProvider && typeof authProvider.getUserSecrets === "function") {
|
|
101
|
+
userSecrets = await authProvider.getUserSecrets(token, options.projectId);
|
|
102
|
+
} else {
|
|
103
|
+
console.warn('[Auth] Auth provider does not support user secrets. Only the LeanMCP provider supports @RequireEnv and getEnv(). Use: new AuthProvider("leanmcp", { apiKey: "..." })');
|
|
104
|
+
}
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.warn("[Auth] Failed to fetch user secrets:", error instanceof Error ? error.message : error);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return await authUserStorage.run(user, async () => {
|
|
110
|
+
if (options.projectId) {
|
|
111
|
+
const { runWithEnv } = await import("@leanmcp/env-injection");
|
|
112
|
+
return await runWithEnv(userSecrets, async () => {
|
|
100
113
|
return await originalMethod.apply(this, [
|
|
101
114
|
args
|
|
102
115
|
]);
|
|
103
116
|
});
|
|
104
117
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
]);
|
|
110
|
-
});
|
|
111
|
-
}
|
|
118
|
+
return await originalMethod.apply(this, [
|
|
119
|
+
args
|
|
120
|
+
]);
|
|
121
|
+
});
|
|
112
122
|
};
|
|
113
123
|
}
|
|
114
124
|
__name(createAuthenticatedMethod, "createAuthenticatedMethod");
|
|
@@ -165,25 +175,31 @@ var AuthProvider = class extends AuthProviderBase {
|
|
|
165
175
|
const finalConfig = config || this.config;
|
|
166
176
|
switch (this.providerType) {
|
|
167
177
|
case "cognito": {
|
|
168
|
-
const { AuthCognito } = await import("./cognito-
|
|
178
|
+
const { AuthCognito } = await import("./cognito-5Q5HGYMA.mjs");
|
|
169
179
|
this.providerInstance = new AuthCognito();
|
|
170
180
|
await this.providerInstance.init(finalConfig);
|
|
171
181
|
break;
|
|
172
182
|
}
|
|
173
183
|
case "auth0": {
|
|
174
|
-
const { AuthAuth0 } = await import("./auth0-
|
|
184
|
+
const { AuthAuth0 } = await import("./auth0-DMNC3QWJ.mjs");
|
|
175
185
|
this.providerInstance = new AuthAuth0();
|
|
176
186
|
await this.providerInstance.init(finalConfig);
|
|
177
187
|
break;
|
|
178
188
|
}
|
|
179
189
|
case "clerk": {
|
|
180
|
-
const { AuthClerk } = await import("./clerk-
|
|
190
|
+
const { AuthClerk } = await import("./clerk-7PVVTTC7.mjs");
|
|
181
191
|
this.providerInstance = new AuthClerk();
|
|
182
192
|
await this.providerInstance.init(finalConfig);
|
|
183
193
|
break;
|
|
184
194
|
}
|
|
195
|
+
case "leanmcp": {
|
|
196
|
+
const { AuthLeanmcp } = await import("./leanmcp-X6BD6HOJ.mjs");
|
|
197
|
+
this.providerInstance = new AuthLeanmcp();
|
|
198
|
+
await this.providerInstance.init(finalConfig);
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
185
201
|
default:
|
|
186
|
-
throw new Error(`Unsupported auth provider: ${this.providerType}. Supported providers: cognito`);
|
|
202
|
+
throw new Error(`Unsupported auth provider: ${this.providerType}. Supported providers: cognito, auth0, clerk, leanmcp`);
|
|
187
203
|
}
|
|
188
204
|
}
|
|
189
205
|
/**
|
|
@@ -214,6 +230,19 @@ var AuthProvider = class extends AuthProviderBase {
|
|
|
214
230
|
return this.providerInstance.getUser(token);
|
|
215
231
|
}
|
|
216
232
|
/**
|
|
233
|
+
* Get user secrets for a project (LeanMCP provider only)
|
|
234
|
+
* Other providers will return empty object
|
|
235
|
+
*/
|
|
236
|
+
async getUserSecrets(token, projectId) {
|
|
237
|
+
if (!this.providerInstance) {
|
|
238
|
+
throw new Error("AuthProvider not initialized. Call init() first.");
|
|
239
|
+
}
|
|
240
|
+
if ("getUserSecrets" in this.providerInstance && typeof this.providerInstance.getUserSecrets === "function") {
|
|
241
|
+
return this.providerInstance.getUserSecrets(token, projectId);
|
|
242
|
+
}
|
|
243
|
+
return {};
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
217
246
|
* Get the provider type
|
|
218
247
|
*/
|
|
219
248
|
getProviderType() {
|
package/dist/index.d.mts
CHANGED
|
@@ -10,6 +10,12 @@ interface AuthenticatedOptions {
|
|
|
10
10
|
* @default true
|
|
11
11
|
*/
|
|
12
12
|
getUser?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Project ID for fetching user environment variables.
|
|
15
|
+
* Required when @RequireEnv is used on the method or class.
|
|
16
|
+
* Used to scope user secrets to a specific project.
|
|
17
|
+
*/
|
|
18
|
+
projectId?: string;
|
|
13
19
|
}
|
|
14
20
|
|
|
15
21
|
/**
|
|
@@ -161,6 +167,11 @@ declare class AuthProvider extends AuthProviderBase {
|
|
|
161
167
|
* Get user information from a token
|
|
162
168
|
*/
|
|
163
169
|
getUser(token: string): Promise<any>;
|
|
170
|
+
/**
|
|
171
|
+
* Get user secrets for a project (LeanMCP provider only)
|
|
172
|
+
* Other providers will return empty object
|
|
173
|
+
*/
|
|
174
|
+
getUserSecrets(token: string, projectId: string): Promise<Record<string, string>>;
|
|
164
175
|
/**
|
|
165
176
|
* Get the provider type
|
|
166
177
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,12 @@ interface AuthenticatedOptions {
|
|
|
10
10
|
* @default true
|
|
11
11
|
*/
|
|
12
12
|
getUser?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Project ID for fetching user environment variables.
|
|
15
|
+
* Required when @RequireEnv is used on the method or class.
|
|
16
|
+
* Used to scope user secrets to a specific project.
|
|
17
|
+
*/
|
|
18
|
+
projectId?: string;
|
|
13
19
|
}
|
|
14
20
|
|
|
15
21
|
/**
|
|
@@ -161,6 +167,11 @@ declare class AuthProvider extends AuthProviderBase {
|
|
|
161
167
|
* Get user information from a token
|
|
162
168
|
*/
|
|
163
169
|
getUser(token: string): Promise<any>;
|
|
170
|
+
/**
|
|
171
|
+
* Get user secrets for a project (LeanMCP provider only)
|
|
172
|
+
* Other providers will return empty object
|
|
173
|
+
*/
|
|
174
|
+
getUserSecrets(token: string, projectId: string): Promise<Record<string, string>>;
|
|
164
175
|
/**
|
|
165
176
|
* Get the provider type
|
|
166
177
|
*/
|
package/dist/index.js
CHANGED
|
@@ -89,29 +89,39 @@ function createAuthenticatedMethod(originalMethod, authProvider, options) {
|
|
|
89
89
|
}
|
|
90
90
|
throw new AuthenticationError(`Token verification failed: ${error instanceof Error ? error.message : String(error)}`, "VERIFICATION_FAILED");
|
|
91
91
|
}
|
|
92
|
+
let user = void 0;
|
|
92
93
|
if (options.getUser !== false) {
|
|
93
94
|
try {
|
|
94
|
-
|
|
95
|
-
return await authUserStorage.run(user, async () => {
|
|
96
|
-
return await originalMethod.apply(this, [
|
|
97
|
-
args
|
|
98
|
-
]);
|
|
99
|
-
});
|
|
95
|
+
user = await authProvider.getUser(token);
|
|
100
96
|
} catch (error) {
|
|
101
97
|
console.warn("Failed to fetch user information:", error);
|
|
102
|
-
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
let userSecrets = {};
|
|
101
|
+
if (options.projectId) {
|
|
102
|
+
try {
|
|
103
|
+
if ("getUserSecrets" in authProvider && typeof authProvider.getUserSecrets === "function") {
|
|
104
|
+
userSecrets = await authProvider.getUserSecrets(token, options.projectId);
|
|
105
|
+
} else {
|
|
106
|
+
console.warn('[Auth] Auth provider does not support user secrets. Only the LeanMCP provider supports @RequireEnv and getEnv(). Use: new AuthProvider("leanmcp", { apiKey: "..." })');
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.warn("[Auth] Failed to fetch user secrets:", error instanceof Error ? error.message : error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return await authUserStorage.run(user, async () => {
|
|
113
|
+
if (options.projectId) {
|
|
114
|
+
const { runWithEnv } = await import("@leanmcp/env-injection");
|
|
115
|
+
return await runWithEnv(userSecrets, async () => {
|
|
103
116
|
return await originalMethod.apply(this, [
|
|
104
117
|
args
|
|
105
118
|
]);
|
|
106
119
|
});
|
|
107
120
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
]);
|
|
113
|
-
});
|
|
114
|
-
}
|
|
121
|
+
return await originalMethod.apply(this, [
|
|
122
|
+
args
|
|
123
|
+
]);
|
|
124
|
+
});
|
|
115
125
|
};
|
|
116
126
|
}
|
|
117
127
|
function copyMetadata(source, target) {
|
|
@@ -547,6 +557,148 @@ var init_clerk = __esm({
|
|
|
547
557
|
}
|
|
548
558
|
});
|
|
549
559
|
|
|
560
|
+
// src/providers/leanmcp.ts
|
|
561
|
+
var leanmcp_exports = {};
|
|
562
|
+
__export(leanmcp_exports, {
|
|
563
|
+
AuthLeanmcp: () => AuthLeanmcp
|
|
564
|
+
});
|
|
565
|
+
var import_axios4, import_jsonwebtoken4, AuthLeanmcp;
|
|
566
|
+
var init_leanmcp = __esm({
|
|
567
|
+
"src/providers/leanmcp.ts"() {
|
|
568
|
+
"use strict";
|
|
569
|
+
import_axios4 = __toESM(require("axios"));
|
|
570
|
+
import_jsonwebtoken4 = __toESM(require("jsonwebtoken"));
|
|
571
|
+
init_index();
|
|
572
|
+
AuthLeanmcp = class extends AuthProviderBase {
|
|
573
|
+
static {
|
|
574
|
+
__name(this, "AuthLeanmcp");
|
|
575
|
+
}
|
|
576
|
+
authUrl = "https://auth.leanmcp.com";
|
|
577
|
+
orchestrationApiUrl = "https://api.leanmcp.com";
|
|
578
|
+
apiKey;
|
|
579
|
+
async init(config) {
|
|
580
|
+
this.authUrl = config?.authUrl || process.env.LEANMCP_AUTH_URL || "https://auth.leanmcp.com";
|
|
581
|
+
this.orchestrationApiUrl = config?.orchestrationApiUrl || process.env.LEANMCP_ORCHESTRATION_API_URL || "https://qaapi.leanmcp.com";
|
|
582
|
+
this.apiKey = config?.apiKey || process.env.LEANMCP_API_KEY;
|
|
583
|
+
}
|
|
584
|
+
async refreshToken(refreshToken) {
|
|
585
|
+
const url = `${this.authUrl}/api/refresh`;
|
|
586
|
+
try {
|
|
587
|
+
const { data } = await import_axios4.default.post(url, {
|
|
588
|
+
refresh_token: refreshToken
|
|
589
|
+
}, {
|
|
590
|
+
headers: {
|
|
591
|
+
"Content-Type": "application/json"
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
return data;
|
|
595
|
+
} catch (error) {
|
|
596
|
+
if (import_axios4.default.isAxiosError(error) && error.response) {
|
|
597
|
+
throw new Error(`Failed to refresh token: ${error.response.data.error?.message || error.response.data.error || "Unknown error"}`);
|
|
598
|
+
}
|
|
599
|
+
throw error;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
async verifyToken(token) {
|
|
603
|
+
if (this.apiKey) {
|
|
604
|
+
const url2 = `${this.orchestrationApiUrl}/public/auth/verify-user`;
|
|
605
|
+
try {
|
|
606
|
+
await import_axios4.default.post(url2, {
|
|
607
|
+
token
|
|
608
|
+
}, {
|
|
609
|
+
headers: {
|
|
610
|
+
"Content-Type": "application/json",
|
|
611
|
+
"x-api-key": this.apiKey
|
|
612
|
+
}
|
|
613
|
+
});
|
|
614
|
+
return true;
|
|
615
|
+
} catch (error) {
|
|
616
|
+
console.error("Failed to verify token:", error);
|
|
617
|
+
return false;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
const url = `${this.authUrl}/api/verify`;
|
|
621
|
+
try {
|
|
622
|
+
const { data } = await import_axios4.default.post(url, {
|
|
623
|
+
token
|
|
624
|
+
}, {
|
|
625
|
+
headers: {
|
|
626
|
+
"Content-Type": "application/json"
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
return data.valid;
|
|
630
|
+
} catch (error) {
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
async getUser(token) {
|
|
635
|
+
if (this.apiKey) {
|
|
636
|
+
const url = `${this.orchestrationApiUrl}/public/auth/verify-user`;
|
|
637
|
+
try {
|
|
638
|
+
const { data } = await import_axios4.default.post(url, {
|
|
639
|
+
token
|
|
640
|
+
}, {
|
|
641
|
+
headers: {
|
|
642
|
+
"Content-Type": "application/json",
|
|
643
|
+
"x-api-key": this.apiKey
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
return {
|
|
647
|
+
uid: data.uid,
|
|
648
|
+
email: data.email,
|
|
649
|
+
email_verified: data.emailVerified,
|
|
650
|
+
name: data.name,
|
|
651
|
+
picture: data.picture,
|
|
652
|
+
type: "firebase"
|
|
653
|
+
};
|
|
654
|
+
} catch (error) {
|
|
655
|
+
console.error("Failed to verify user token via Orchestration API:", error.response?.data || error.message);
|
|
656
|
+
throw new Error("Invalid user token or API key");
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
const decoded = import_jsonwebtoken4.default.decode(token);
|
|
660
|
+
if (!decoded) throw new Error("Invalid ID token");
|
|
661
|
+
return {
|
|
662
|
+
uid: decoded.user_id || decoded.sub,
|
|
663
|
+
email: decoded.email,
|
|
664
|
+
email_verified: decoded.email_verified,
|
|
665
|
+
name: decoded.name || decoded.displayName,
|
|
666
|
+
picture: decoded.picture || decoded.photoURL,
|
|
667
|
+
attributes: decoded,
|
|
668
|
+
type: "jwt"
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Fetch user-specific environment variables for a project
|
|
673
|
+
* Uses the user's UID and project ID to retrieve their stored secrets
|
|
674
|
+
*
|
|
675
|
+
* @param token - User's auth token
|
|
676
|
+
* @param projectId - Project ID to scope the secrets
|
|
677
|
+
* @returns Record of environment variables
|
|
678
|
+
*/
|
|
679
|
+
async getUserSecrets(token, projectId) {
|
|
680
|
+
if (!this.apiKey) {
|
|
681
|
+
console.warn("[LeanMCP] API key not configured - cannot fetch user secrets. Set LEANMCP_API_KEY environment variable or pass apiKey in config.");
|
|
682
|
+
return {};
|
|
683
|
+
}
|
|
684
|
+
const url = `${this.orchestrationApiUrl}/public/secrets/user/${projectId}`;
|
|
685
|
+
try {
|
|
686
|
+
const { data } = await import_axios4.default.get(url, {
|
|
687
|
+
headers: {
|
|
688
|
+
"Authorization": `Bearer ${token}`,
|
|
689
|
+
"x-api-key": this.apiKey
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
return data.secrets || {};
|
|
693
|
+
} catch (error) {
|
|
694
|
+
console.warn("[LeanMCP] Failed to fetch user secrets:", error.response?.status || error.message);
|
|
695
|
+
return {};
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
|
|
550
702
|
// src/index.ts
|
|
551
703
|
var index_exports = {};
|
|
552
704
|
__export(index_exports, {
|
|
@@ -605,8 +757,14 @@ var init_index = __esm({
|
|
|
605
757
|
await this.providerInstance.init(finalConfig);
|
|
606
758
|
break;
|
|
607
759
|
}
|
|
760
|
+
case "leanmcp": {
|
|
761
|
+
const { AuthLeanmcp: AuthLeanmcp2 } = await Promise.resolve().then(() => (init_leanmcp(), leanmcp_exports));
|
|
762
|
+
this.providerInstance = new AuthLeanmcp2();
|
|
763
|
+
await this.providerInstance.init(finalConfig);
|
|
764
|
+
break;
|
|
765
|
+
}
|
|
608
766
|
default:
|
|
609
|
-
throw new Error(`Unsupported auth provider: ${this.providerType}. Supported providers: cognito`);
|
|
767
|
+
throw new Error(`Unsupported auth provider: ${this.providerType}. Supported providers: cognito, auth0, clerk, leanmcp`);
|
|
610
768
|
}
|
|
611
769
|
}
|
|
612
770
|
/**
|
|
@@ -637,6 +795,19 @@ var init_index = __esm({
|
|
|
637
795
|
return this.providerInstance.getUser(token);
|
|
638
796
|
}
|
|
639
797
|
/**
|
|
798
|
+
* Get user secrets for a project (LeanMCP provider only)
|
|
799
|
+
* Other providers will return empty object
|
|
800
|
+
*/
|
|
801
|
+
async getUserSecrets(token, projectId) {
|
|
802
|
+
if (!this.providerInstance) {
|
|
803
|
+
throw new Error("AuthProvider not initialized. Call init() first.");
|
|
804
|
+
}
|
|
805
|
+
if ("getUserSecrets" in this.providerInstance && typeof this.providerInstance.getUserSecrets === "function") {
|
|
806
|
+
return this.providerInstance.getUserSecrets(token, projectId);
|
|
807
|
+
}
|
|
808
|
+
return {};
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
640
811
|
* Get the provider type
|
|
641
812
|
*/
|
|
642
813
|
getProviderType() {
|
package/dist/index.mjs
CHANGED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AuthProviderBase,
|
|
3
|
+
__name
|
|
4
|
+
} from "./chunk-ESHQ6BRM.mjs";
|
|
5
|
+
|
|
6
|
+
// src/providers/leanmcp.ts
|
|
7
|
+
import axios from "axios";
|
|
8
|
+
import jwt from "jsonwebtoken";
|
|
9
|
+
var AuthLeanmcp = class extends AuthProviderBase {
|
|
10
|
+
static {
|
|
11
|
+
__name(this, "AuthLeanmcp");
|
|
12
|
+
}
|
|
13
|
+
authUrl = "https://auth.leanmcp.com";
|
|
14
|
+
orchestrationApiUrl = "https://api.leanmcp.com";
|
|
15
|
+
apiKey;
|
|
16
|
+
async init(config) {
|
|
17
|
+
this.authUrl = config?.authUrl || process.env.LEANMCP_AUTH_URL || "https://auth.leanmcp.com";
|
|
18
|
+
this.orchestrationApiUrl = config?.orchestrationApiUrl || process.env.LEANMCP_ORCHESTRATION_API_URL || "https://qaapi.leanmcp.com";
|
|
19
|
+
this.apiKey = config?.apiKey || process.env.LEANMCP_API_KEY;
|
|
20
|
+
}
|
|
21
|
+
async refreshToken(refreshToken) {
|
|
22
|
+
const url = `${this.authUrl}/api/refresh`;
|
|
23
|
+
try {
|
|
24
|
+
const { data } = await axios.post(url, {
|
|
25
|
+
refresh_token: refreshToken
|
|
26
|
+
}, {
|
|
27
|
+
headers: {
|
|
28
|
+
"Content-Type": "application/json"
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return data;
|
|
32
|
+
} catch (error) {
|
|
33
|
+
if (axios.isAxiosError(error) && error.response) {
|
|
34
|
+
throw new Error(`Failed to refresh token: ${error.response.data.error?.message || error.response.data.error || "Unknown error"}`);
|
|
35
|
+
}
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async verifyToken(token) {
|
|
40
|
+
if (this.apiKey) {
|
|
41
|
+
const url2 = `${this.orchestrationApiUrl}/public/auth/verify-user`;
|
|
42
|
+
try {
|
|
43
|
+
await axios.post(url2, {
|
|
44
|
+
token
|
|
45
|
+
}, {
|
|
46
|
+
headers: {
|
|
47
|
+
"Content-Type": "application/json",
|
|
48
|
+
"x-api-key": this.apiKey
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return true;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error("Failed to verify token:", error);
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const url = `${this.authUrl}/api/verify`;
|
|
58
|
+
try {
|
|
59
|
+
const { data } = await axios.post(url, {
|
|
60
|
+
token
|
|
61
|
+
}, {
|
|
62
|
+
headers: {
|
|
63
|
+
"Content-Type": "application/json"
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return data.valid;
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async getUser(token) {
|
|
72
|
+
if (this.apiKey) {
|
|
73
|
+
const url = `${this.orchestrationApiUrl}/public/auth/verify-user`;
|
|
74
|
+
try {
|
|
75
|
+
const { data } = await axios.post(url, {
|
|
76
|
+
token
|
|
77
|
+
}, {
|
|
78
|
+
headers: {
|
|
79
|
+
"Content-Type": "application/json",
|
|
80
|
+
"x-api-key": this.apiKey
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
uid: data.uid,
|
|
85
|
+
email: data.email,
|
|
86
|
+
email_verified: data.emailVerified,
|
|
87
|
+
name: data.name,
|
|
88
|
+
picture: data.picture,
|
|
89
|
+
type: "firebase"
|
|
90
|
+
};
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error("Failed to verify user token via Orchestration API:", error.response?.data || error.message);
|
|
93
|
+
throw new Error("Invalid user token or API key");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const decoded = jwt.decode(token);
|
|
97
|
+
if (!decoded) throw new Error("Invalid ID token");
|
|
98
|
+
return {
|
|
99
|
+
uid: decoded.user_id || decoded.sub,
|
|
100
|
+
email: decoded.email,
|
|
101
|
+
email_verified: decoded.email_verified,
|
|
102
|
+
name: decoded.name || decoded.displayName,
|
|
103
|
+
picture: decoded.picture || decoded.photoURL,
|
|
104
|
+
attributes: decoded,
|
|
105
|
+
type: "jwt"
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Fetch user-specific environment variables for a project
|
|
110
|
+
* Uses the user's UID and project ID to retrieve their stored secrets
|
|
111
|
+
*
|
|
112
|
+
* @param token - User's auth token
|
|
113
|
+
* @param projectId - Project ID to scope the secrets
|
|
114
|
+
* @returns Record of environment variables
|
|
115
|
+
*/
|
|
116
|
+
async getUserSecrets(token, projectId) {
|
|
117
|
+
if (!this.apiKey) {
|
|
118
|
+
console.warn("[LeanMCP] API key not configured - cannot fetch user secrets. Set LEANMCP_API_KEY environment variable or pass apiKey in config.");
|
|
119
|
+
return {};
|
|
120
|
+
}
|
|
121
|
+
const url = `${this.orchestrationApiUrl}/public/secrets/user/${projectId}`;
|
|
122
|
+
try {
|
|
123
|
+
const { data } = await axios.get(url, {
|
|
124
|
+
headers: {
|
|
125
|
+
"Authorization": `Bearer ${token}`,
|
|
126
|
+
"x-api-key": this.apiKey
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return data.secrets || {};
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.warn("[LeanMCP] Failed to fetch user secrets:", error.response?.status || error.message);
|
|
132
|
+
return {};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
export {
|
|
137
|
+
AuthLeanmcp
|
|
138
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leanmcp/auth",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Authentication and identity module supporting multiple providers",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@aws-sdk/client-cognito-identity-provider": "^3.0.0",
|
|
41
|
+
"@leanmcp/env-injection": "^0.1.0",
|
|
41
42
|
"axios": "^1.0.0",
|
|
42
43
|
"jsonwebtoken": "^9.0.0",
|
|
43
44
|
"jwk-to-pem": "^2.0.0"
|
|
@@ -46,6 +47,9 @@
|
|
|
46
47
|
"@aws-sdk/client-cognito-identity-provider": {
|
|
47
48
|
"optional": true
|
|
48
49
|
},
|
|
50
|
+
"@leanmcp/env-injection": {
|
|
51
|
+
"optional": true
|
|
52
|
+
},
|
|
49
53
|
"axios": {
|
|
50
54
|
"optional": true
|
|
51
55
|
},
|
|
@@ -80,4 +84,4 @@
|
|
|
80
84
|
"publishConfig": {
|
|
81
85
|
"access": "public"
|
|
82
86
|
}
|
|
83
|
-
}
|
|
87
|
+
}
|