@leanmcp/auth 0.3.1 → 0.4.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.
@@ -1,7 +1,9 @@
1
1
  import {
2
- AuthProviderBase,
2
+ AuthProviderBase
3
+ } from "./chunk-P4HFKA5R.mjs";
4
+ import {
3
5
  __name
4
- } from "./chunk-EVD2TRPR.mjs";
6
+ } from "./chunk-LPEX4YW6.mjs";
5
7
 
6
8
  // src/providers/cognito.ts
7
9
  import { CognitoIdentityProviderClient, InitiateAuthCommand } from "@aws-sdk/client-cognito-identity-provider";
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
- const user = await authProvider.getUser(token);
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
- return await authUserStorage.run(void 0, async () => {
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
- } else {
109
- return await authUserStorage.run(void 0, async () => {
110
- return await originalMethod.apply(this, [
111
- args
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
@@ -6,7 +6,8 @@ import {
6
6
  getAuthProvider,
7
7
  getAuthUser,
8
8
  isAuthenticationRequired
9
- } from "./chunk-EVD2TRPR.mjs";
9
+ } from "./chunk-P4HFKA5R.mjs";
10
+ import "./chunk-LPEX4YW6.mjs";
10
11
  export {
11
12
  AuthProvider,
12
13
  AuthProviderBase,
@@ -0,0 +1,140 @@
1
+ import {
2
+ AuthProviderBase
3
+ } from "./chunk-P4HFKA5R.mjs";
4
+ import {
5
+ __name
6
+ } from "./chunk-LPEX4YW6.mjs";
7
+
8
+ // src/providers/leanmcp.ts
9
+ import axios from "axios";
10
+ import jwt from "jsonwebtoken";
11
+ var AuthLeanmcp = class extends AuthProviderBase {
12
+ static {
13
+ __name(this, "AuthLeanmcp");
14
+ }
15
+ authUrl = "https://auth.leanmcp.com";
16
+ orchestrationApiUrl = "https://api.leanmcp.com";
17
+ apiKey;
18
+ async init(config) {
19
+ this.authUrl = config?.authUrl || process.env.LEANMCP_AUTH_URL || "https://auth.leanmcp.com";
20
+ this.orchestrationApiUrl = config?.orchestrationApiUrl || process.env.LEANMCP_ORCHESTRATION_API_URL || "https://qaapi.leanmcp.com";
21
+ this.apiKey = config?.apiKey || process.env.LEANMCP_API_KEY;
22
+ }
23
+ async refreshToken(refreshToken) {
24
+ const url = `${this.authUrl}/api/refresh`;
25
+ try {
26
+ const { data } = await axios.post(url, {
27
+ refresh_token: refreshToken
28
+ }, {
29
+ headers: {
30
+ "Content-Type": "application/json"
31
+ }
32
+ });
33
+ return data;
34
+ } catch (error) {
35
+ if (axios.isAxiosError(error) && error.response) {
36
+ throw new Error(`Failed to refresh token: ${error.response.data.error?.message || error.response.data.error || "Unknown error"}`);
37
+ }
38
+ throw error;
39
+ }
40
+ }
41
+ async verifyToken(token) {
42
+ if (this.apiKey) {
43
+ const url2 = `${this.orchestrationApiUrl}/public/auth/verify-user`;
44
+ try {
45
+ await axios.post(url2, {
46
+ token
47
+ }, {
48
+ headers: {
49
+ "Content-Type": "application/json",
50
+ "x-api-key": this.apiKey
51
+ }
52
+ });
53
+ return true;
54
+ } catch (error) {
55
+ console.error("Failed to verify token:", error);
56
+ return false;
57
+ }
58
+ }
59
+ const url = `${this.authUrl}/api/verify`;
60
+ try {
61
+ const { data } = await axios.post(url, {
62
+ token
63
+ }, {
64
+ headers: {
65
+ "Content-Type": "application/json"
66
+ }
67
+ });
68
+ return data.valid;
69
+ } catch (error) {
70
+ return false;
71
+ }
72
+ }
73
+ async getUser(token) {
74
+ if (this.apiKey) {
75
+ const url = `${this.orchestrationApiUrl}/public/auth/verify-user`;
76
+ try {
77
+ const { data } = await axios.post(url, {
78
+ token
79
+ }, {
80
+ headers: {
81
+ "Content-Type": "application/json",
82
+ "x-api-key": this.apiKey
83
+ }
84
+ });
85
+ return {
86
+ uid: data.uid,
87
+ email: data.email,
88
+ email_verified: data.emailVerified,
89
+ name: data.name,
90
+ picture: data.picture,
91
+ type: "firebase"
92
+ };
93
+ } catch (error) {
94
+ console.error("Failed to verify user token via Orchestration API:", error.response?.data || error.message);
95
+ throw new Error("Invalid user token or API key");
96
+ }
97
+ }
98
+ const decoded = jwt.decode(token);
99
+ if (!decoded) throw new Error("Invalid ID token");
100
+ return {
101
+ uid: decoded.user_id || decoded.sub,
102
+ email: decoded.email,
103
+ email_verified: decoded.email_verified,
104
+ name: decoded.name || decoded.displayName,
105
+ picture: decoded.picture || decoded.photoURL,
106
+ attributes: decoded,
107
+ type: "jwt"
108
+ };
109
+ }
110
+ /**
111
+ * Fetch user-specific environment variables for a project
112
+ * Uses the user's UID and project ID to retrieve their stored secrets
113
+ *
114
+ * @param token - User's auth token
115
+ * @param projectId - Project ID to scope the secrets
116
+ * @returns Record of environment variables
117
+ */
118
+ async getUserSecrets(token, projectId) {
119
+ if (!this.apiKey) {
120
+ console.warn("[LeanMCP] API key not configured - cannot fetch user secrets. Set LEANMCP_API_KEY environment variable or pass apiKey in config.");
121
+ return {};
122
+ }
123
+ const url = `${this.orchestrationApiUrl}/public/secrets/user/${projectId}`;
124
+ try {
125
+ const { data } = await axios.get(url, {
126
+ headers: {
127
+ "Authorization": `Bearer ${token}`,
128
+ "x-api-key": this.apiKey
129
+ }
130
+ });
131
+ return data.secrets || {};
132
+ } catch (error) {
133
+ console.warn("[LeanMCP] Failed to fetch user secrets:", error.response?.status || error.message);
134
+ return {};
135
+ }
136
+ }
137
+ };
138
+ export {
139
+ AuthLeanmcp
140
+ };