@lanonasis/oauth-client 1.2.6 → 1.2.8

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.
@@ -29,6 +29,42 @@ interface PKCEChallenge {
29
29
  codeVerifier: string;
30
30
  codeChallenge: string;
31
31
  }
32
+ type AuthTokenType = 'api_key' | 'jwt' | 'oauth' | 'cli';
33
+ interface AuthValidationResult {
34
+ valid: boolean;
35
+ type?: AuthTokenType;
36
+ userId?: string;
37
+ email?: string;
38
+ role?: string;
39
+ projectScope?: string;
40
+ permissions?: string[];
41
+ scope?: string | string[];
42
+ expiresAt?: string | null;
43
+ error?: string;
44
+ raw?: unknown;
45
+ }
46
+ interface AuthGatewayClientConfig {
47
+ authBaseUrl?: string;
48
+ clientId?: string;
49
+ projectScope?: string;
50
+ }
51
+ interface TokenExchangeOptions {
52
+ projectScope?: string;
53
+ platform?: string;
54
+ }
55
+ interface TokenExchangeResponse {
56
+ access_token: string;
57
+ refresh_token: string;
58
+ expires_in: number;
59
+ token_type?: string;
60
+ user?: {
61
+ id: string;
62
+ email?: string;
63
+ role?: string;
64
+ project_scope?: string;
65
+ };
66
+ [key: string]: unknown;
67
+ }
32
68
 
33
69
  declare abstract class BaseOAuthFlow {
34
70
  protected readonly clientId: string;
@@ -91,6 +127,22 @@ declare class TokenStorage implements TokenStorageAdapter {
91
127
  private getWebEncryptionKey;
92
128
  }
93
129
 
130
+ declare class AuthGatewayClient {
131
+ private authBaseUrl;
132
+ private projectScope;
133
+ private flow;
134
+ constructor(config?: AuthGatewayClientConfig);
135
+ exchangeSupabaseToken(supabaseToken: string, options?: TokenExchangeOptions): Promise<TokenExchangeResponse>;
136
+ refreshToken(refreshToken: string): Promise<TokenResponse>;
137
+ revokeToken(token: string, tokenType?: 'access_token' | 'refresh_token'): Promise<void>;
138
+ validateToken(token: string): Promise<AuthValidationResult>;
139
+ verifyApiKey(apiKey: string): Promise<AuthValidationResult>;
140
+ verifyToken(token: string): Promise<AuthValidationResult>;
141
+ introspectToken(token: string): Promise<AuthValidationResult>;
142
+ private normalizeTokenType;
143
+ private requestJson;
144
+ }
145
+
94
146
  /**
95
147
  * Browser-only token storage that avoids Node/Electron dependencies.
96
148
  * Tokens are encrypted with Web Crypto and stored in localStorage.
@@ -205,4 +257,4 @@ declare class ApiKeyStorageWeb {
205
257
  private base64Decode;
206
258
  }
207
259
 
208
- export { ApiKeyStorageWeb as A, BaseOAuthFlow as B, DesktopOAuthFlow as D, type GrantType as G, type OAuthConfig as O, type PKCEChallenge as P, type TokenStorageAdapter as T, TokenStorageWeb as a, type TokenResponse as b, type DeviceCodeResponse as c, type AuthError as d, TokenStorage as e, type ApiKeyData as f, ApiKeyStorage as g };
260
+ export { AuthGatewayClient as A, BaseOAuthFlow as B, DesktopOAuthFlow as D, type GrantType as G, type OAuthConfig as O, type PKCEChallenge as P, type TokenStorageAdapter as T, TokenStorageWeb as a, ApiKeyStorageWeb as b, type TokenResponse as c, type DeviceCodeResponse as d, type AuthError as e, type AuthTokenType as f, type AuthValidationResult as g, type AuthGatewayClientConfig as h, type TokenExchangeOptions as i, type TokenExchangeResponse as j, TokenStorage as k, type ApiKeyData as l, ApiKeyStorage as m };
@@ -29,6 +29,42 @@ interface PKCEChallenge {
29
29
  codeVerifier: string;
30
30
  codeChallenge: string;
31
31
  }
32
+ type AuthTokenType = 'api_key' | 'jwt' | 'oauth' | 'cli';
33
+ interface AuthValidationResult {
34
+ valid: boolean;
35
+ type?: AuthTokenType;
36
+ userId?: string;
37
+ email?: string;
38
+ role?: string;
39
+ projectScope?: string;
40
+ permissions?: string[];
41
+ scope?: string | string[];
42
+ expiresAt?: string | null;
43
+ error?: string;
44
+ raw?: unknown;
45
+ }
46
+ interface AuthGatewayClientConfig {
47
+ authBaseUrl?: string;
48
+ clientId?: string;
49
+ projectScope?: string;
50
+ }
51
+ interface TokenExchangeOptions {
52
+ projectScope?: string;
53
+ platform?: string;
54
+ }
55
+ interface TokenExchangeResponse {
56
+ access_token: string;
57
+ refresh_token: string;
58
+ expires_in: number;
59
+ token_type?: string;
60
+ user?: {
61
+ id: string;
62
+ email?: string;
63
+ role?: string;
64
+ project_scope?: string;
65
+ };
66
+ [key: string]: unknown;
67
+ }
32
68
 
33
69
  declare abstract class BaseOAuthFlow {
34
70
  protected readonly clientId: string;
@@ -91,6 +127,22 @@ declare class TokenStorage implements TokenStorageAdapter {
91
127
  private getWebEncryptionKey;
92
128
  }
93
129
 
130
+ declare class AuthGatewayClient {
131
+ private authBaseUrl;
132
+ private projectScope;
133
+ private flow;
134
+ constructor(config?: AuthGatewayClientConfig);
135
+ exchangeSupabaseToken(supabaseToken: string, options?: TokenExchangeOptions): Promise<TokenExchangeResponse>;
136
+ refreshToken(refreshToken: string): Promise<TokenResponse>;
137
+ revokeToken(token: string, tokenType?: 'access_token' | 'refresh_token'): Promise<void>;
138
+ validateToken(token: string): Promise<AuthValidationResult>;
139
+ verifyApiKey(apiKey: string): Promise<AuthValidationResult>;
140
+ verifyToken(token: string): Promise<AuthValidationResult>;
141
+ introspectToken(token: string): Promise<AuthValidationResult>;
142
+ private normalizeTokenType;
143
+ private requestJson;
144
+ }
145
+
94
146
  /**
95
147
  * Browser-only token storage that avoids Node/Electron dependencies.
96
148
  * Tokens are encrypted with Web Crypto and stored in localStorage.
@@ -205,4 +257,4 @@ declare class ApiKeyStorageWeb {
205
257
  private base64Decode;
206
258
  }
207
259
 
208
- export { ApiKeyStorageWeb as A, BaseOAuthFlow as B, DesktopOAuthFlow as D, type GrantType as G, type OAuthConfig as O, type PKCEChallenge as P, type TokenStorageAdapter as T, TokenStorageWeb as a, type TokenResponse as b, type DeviceCodeResponse as c, type AuthError as d, TokenStorage as e, type ApiKeyData as f, ApiKeyStorage as g };
260
+ export { AuthGatewayClient as A, BaseOAuthFlow as B, DesktopOAuthFlow as D, type GrantType as G, type OAuthConfig as O, type PKCEChallenge as P, type TokenStorageAdapter as T, TokenStorageWeb as a, ApiKeyStorageWeb as b, type TokenResponse as c, type DeviceCodeResponse as d, type AuthError as e, type AuthTokenType as f, type AuthValidationResult as g, type AuthGatewayClientConfig as h, type TokenExchangeOptions as i, type TokenExchangeResponse as j, TokenStorage as k, type ApiKeyData as l, ApiKeyStorage as m };
package/dist/browser.cjs CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var browser_exports = {};
32
32
  __export(browser_exports, {
33
33
  ApiKeyStorageWeb: () => ApiKeyStorageWeb,
34
+ AuthGatewayClient: () => AuthGatewayClient,
34
35
  BaseOAuthFlow: () => BaseOAuthFlow,
35
36
  DesktopOAuthFlow: () => DesktopOAuthFlow,
36
37
  MCPClient: () => MCPClient,
@@ -432,7 +433,7 @@ var APIKeyFlow = class extends BaseOAuthFlow {
432
433
  */
433
434
  async validateAPIKey() {
434
435
  try {
435
- const response = await (0, import_cross_fetch2.default)(`${this.config.authBaseUrl}/api/v1/health`, {
436
+ const response = await (0, import_cross_fetch2.default)(`${this.authBaseUrl}/api/v1/health`, {
436
437
  headers: {
437
438
  "x-api-key": this.apiKey
438
439
  }
@@ -662,6 +663,192 @@ var MCPClient = class {
662
663
  }
663
664
  };
664
665
 
666
+ // src/client/auth-gateway-client.ts
667
+ var import_cross_fetch4 = __toESM(require("cross-fetch"), 1);
668
+ var GatewayOAuthFlow = class extends BaseOAuthFlow {
669
+ async authenticate() {
670
+ throw new Error("Interactive authentication is not supported in AuthGatewayClient.");
671
+ }
672
+ };
673
+ var DEFAULT_AUTH_BASE_URL = "https://auth.lanonasis.com";
674
+ var DEFAULT_CLIENT_ID = "lanonasis-cli";
675
+ var DEFAULT_PROJECT_SCOPE = "lanonasis-maas";
676
+ var API_KEY_PREFIXES = ["lano_", "pk_", "sk_"];
677
+ var AuthGatewayClient = class {
678
+ constructor(config = {}) {
679
+ const baseUrl = config.authBaseUrl || DEFAULT_AUTH_BASE_URL;
680
+ this.authBaseUrl = baseUrl.replace(/\/+$/, "");
681
+ this.projectScope = config.projectScope || DEFAULT_PROJECT_SCOPE;
682
+ this.flow = new GatewayOAuthFlow({
683
+ clientId: config.clientId || DEFAULT_CLIENT_ID,
684
+ authBaseUrl: this.authBaseUrl
685
+ });
686
+ }
687
+ async exchangeSupabaseToken(supabaseToken, options = {}) {
688
+ const token = typeof supabaseToken === "string" ? supabaseToken.trim() : "";
689
+ if (!token) {
690
+ throw new Error("Supabase access token is required");
691
+ }
692
+ const projectScope = options.projectScope || this.projectScope;
693
+ const platform = options.platform || "web";
694
+ return this.requestJson("/v1/auth/token/exchange", {
695
+ method: "POST",
696
+ headers: {
697
+ Authorization: `Bearer ${token}`,
698
+ "Content-Type": "application/json",
699
+ "X-Project-Scope": projectScope
700
+ },
701
+ body: JSON.stringify({
702
+ project_scope: projectScope,
703
+ platform
704
+ })
705
+ });
706
+ }
707
+ async refreshToken(refreshToken) {
708
+ return this.flow.refreshToken(refreshToken);
709
+ }
710
+ async revokeToken(token, tokenType = "access_token") {
711
+ return this.flow.revokeToken(token, tokenType);
712
+ }
713
+ async validateToken(token) {
714
+ const trimmed = typeof token === "string" ? token.trim() : "";
715
+ if (!trimmed) {
716
+ return { valid: false, error: "Token is required" };
717
+ }
718
+ if (API_KEY_PREFIXES.some((prefix) => trimmed.startsWith(prefix))) {
719
+ return this.verifyApiKey(trimmed);
720
+ }
721
+ if (trimmed.startsWith("cli_") || trimmed.includes(".")) {
722
+ return this.verifyToken(trimmed);
723
+ }
724
+ return this.introspectToken(trimmed);
725
+ }
726
+ async verifyApiKey(apiKey) {
727
+ try {
728
+ const data = await this.requestJson("/v1/auth/verify-api-key", {
729
+ method: "POST",
730
+ headers: {
731
+ "Content-Type": "application/json",
732
+ "X-API-Key": apiKey
733
+ }
734
+ });
735
+ if (!data || data.valid === false) {
736
+ return {
737
+ valid: false,
738
+ type: "api_key",
739
+ error: data && (data.error || data.message) || "Invalid API key",
740
+ raw: data
741
+ };
742
+ }
743
+ return {
744
+ valid: true,
745
+ type: "api_key",
746
+ userId: data.userId,
747
+ projectScope: data.projectScope,
748
+ permissions: data.permissions || [],
749
+ raw: data
750
+ };
751
+ } catch (error) {
752
+ return {
753
+ valid: false,
754
+ type: "api_key",
755
+ error: error?.message || "API key validation failed",
756
+ raw: error?.data
757
+ };
758
+ }
759
+ }
760
+ async verifyToken(token) {
761
+ try {
762
+ const data = await this.requestJson("/v1/auth/verify-token", {
763
+ method: "POST",
764
+ headers: { "Content-Type": "application/json" },
765
+ body: JSON.stringify({ token })
766
+ });
767
+ if (!data || data.valid === false) {
768
+ return {
769
+ valid: false,
770
+ type: data?.type ? this.normalizeTokenType(data.type) : "jwt",
771
+ error: data?.error || "Invalid token",
772
+ raw: data
773
+ };
774
+ }
775
+ return {
776
+ valid: true,
777
+ type: data.type ? this.normalizeTokenType(data.type) : "jwt",
778
+ userId: data.user?.id,
779
+ email: data.user?.email,
780
+ role: data.user?.role,
781
+ expiresAt: data.expires_at || null,
782
+ raw: data
783
+ };
784
+ } catch (error) {
785
+ return {
786
+ valid: false,
787
+ type: "jwt",
788
+ error: error?.message || "Token verification failed",
789
+ raw: error?.data
790
+ };
791
+ }
792
+ }
793
+ async introspectToken(token) {
794
+ try {
795
+ const data = await this.requestJson("/oauth/introspect", {
796
+ method: "POST",
797
+ headers: { "Content-Type": "application/json" },
798
+ body: JSON.stringify({ token })
799
+ });
800
+ if (!data || data.active !== true) {
801
+ return {
802
+ valid: false,
803
+ type: "oauth",
804
+ error: "Token is inactive",
805
+ raw: data
806
+ };
807
+ }
808
+ return {
809
+ valid: true,
810
+ type: "oauth",
811
+ userId: data.user_id || data.sub,
812
+ scope: data.scope,
813
+ expiresAt: data.exp ? new Date(data.exp * 1e3).toISOString() : null,
814
+ raw: data
815
+ };
816
+ } catch (error) {
817
+ return {
818
+ valid: false,
819
+ type: "oauth",
820
+ error: error?.message || "Token introspection failed",
821
+ raw: error?.data
822
+ };
823
+ }
824
+ }
825
+ normalizeTokenType(type) {
826
+ if (type === "cli_token") return "cli";
827
+ if (type === "jwt") return "jwt";
828
+ return "jwt";
829
+ }
830
+ async requestJson(path, options) {
831
+ const response = await (0, import_cross_fetch4.default)(`${this.authBaseUrl}${path.startsWith("/") ? path : `/${path}`}`, options);
832
+ const text = await response.text();
833
+ let data = null;
834
+ if (text) {
835
+ try {
836
+ data = JSON.parse(text);
837
+ } catch (parseError) {
838
+ data = { raw: text };
839
+ }
840
+ }
841
+ if (!response.ok) {
842
+ const message = data?.message || data?.error || `Request failed (${response.status})`;
843
+ const error = new Error(message);
844
+ error.status = response.status;
845
+ error.data = data;
846
+ throw error;
847
+ }
848
+ return data;
849
+ }
850
+ };
851
+
665
852
  // src/storage/api-key-storage-web.ts
666
853
  var ApiKeyStorageWeb = class {
667
854
  constructor() {
@@ -1,5 +1,5 @@
1
- import { O as OAuthConfig, T as TokenStorageAdapter } from './api-key-storage-web-DannE11B.cjs';
2
- export { A as ApiKeyStorageWeb, d as AuthError, B as BaseOAuthFlow, D as DesktopOAuthFlow, c as DeviceCodeResponse, G as GrantType, P as PKCEChallenge, b as TokenResponse, a as TokenStorageWeb } from './api-key-storage-web-DannE11B.cjs';
1
+ import { O as OAuthConfig, T as TokenStorageAdapter } from './api-key-storage-web-J3W8nQi2.cjs';
2
+ export { b as ApiKeyStorageWeb, e as AuthError, A as AuthGatewayClient, h as AuthGatewayClientConfig, f as AuthTokenType, g as AuthValidationResult, B as BaseOAuthFlow, D as DesktopOAuthFlow, d as DeviceCodeResponse, G as GrantType, P as PKCEChallenge, i as TokenExchangeOptions, j as TokenExchangeResponse, c as TokenResponse, a as TokenStorageWeb } from './api-key-storage-web-J3W8nQi2.cjs';
3
3
 
4
4
  interface MCPClientConfig extends Partial<OAuthConfig> {
5
5
  mcpEndpoint?: string;
package/dist/browser.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { O as OAuthConfig, T as TokenStorageAdapter } from './api-key-storage-web-DannE11B.js';
2
- export { A as ApiKeyStorageWeb, d as AuthError, B as BaseOAuthFlow, D as DesktopOAuthFlow, c as DeviceCodeResponse, G as GrantType, P as PKCEChallenge, b as TokenResponse, a as TokenStorageWeb } from './api-key-storage-web-DannE11B.js';
1
+ import { O as OAuthConfig, T as TokenStorageAdapter } from './api-key-storage-web-J3W8nQi2.js';
2
+ export { b as ApiKeyStorageWeb, e as AuthError, A as AuthGatewayClient, h as AuthGatewayClientConfig, f as AuthTokenType, g as AuthValidationResult, B as BaseOAuthFlow, D as DesktopOAuthFlow, d as DeviceCodeResponse, G as GrantType, P as PKCEChallenge, i as TokenExchangeOptions, j as TokenExchangeResponse, c as TokenResponse, a as TokenStorageWeb } from './api-key-storage-web-J3W8nQi2.js';
3
3
 
4
4
  interface MCPClientConfig extends Partial<OAuthConfig> {
5
5
  mcpEndpoint?: string;
package/dist/browser.mjs CHANGED
@@ -399,7 +399,7 @@ var APIKeyFlow = class extends BaseOAuthFlow {
399
399
  */
400
400
  async validateAPIKey() {
401
401
  try {
402
- const response = await fetch2(`${this.config.authBaseUrl}/api/v1/health`, {
402
+ const response = await fetch2(`${this.authBaseUrl}/api/v1/health`, {
403
403
  headers: {
404
404
  "x-api-key": this.apiKey
405
405
  }
@@ -629,6 +629,192 @@ var MCPClient = class {
629
629
  }
630
630
  };
631
631
 
632
+ // src/client/auth-gateway-client.ts
633
+ import fetch4 from "cross-fetch";
634
+ var GatewayOAuthFlow = class extends BaseOAuthFlow {
635
+ async authenticate() {
636
+ throw new Error("Interactive authentication is not supported in AuthGatewayClient.");
637
+ }
638
+ };
639
+ var DEFAULT_AUTH_BASE_URL = "https://auth.lanonasis.com";
640
+ var DEFAULT_CLIENT_ID = "lanonasis-cli";
641
+ var DEFAULT_PROJECT_SCOPE = "lanonasis-maas";
642
+ var API_KEY_PREFIXES = ["lano_", "pk_", "sk_"];
643
+ var AuthGatewayClient = class {
644
+ constructor(config = {}) {
645
+ const baseUrl = config.authBaseUrl || DEFAULT_AUTH_BASE_URL;
646
+ this.authBaseUrl = baseUrl.replace(/\/+$/, "");
647
+ this.projectScope = config.projectScope || DEFAULT_PROJECT_SCOPE;
648
+ this.flow = new GatewayOAuthFlow({
649
+ clientId: config.clientId || DEFAULT_CLIENT_ID,
650
+ authBaseUrl: this.authBaseUrl
651
+ });
652
+ }
653
+ async exchangeSupabaseToken(supabaseToken, options = {}) {
654
+ const token = typeof supabaseToken === "string" ? supabaseToken.trim() : "";
655
+ if (!token) {
656
+ throw new Error("Supabase access token is required");
657
+ }
658
+ const projectScope = options.projectScope || this.projectScope;
659
+ const platform = options.platform || "web";
660
+ return this.requestJson("/v1/auth/token/exchange", {
661
+ method: "POST",
662
+ headers: {
663
+ Authorization: `Bearer ${token}`,
664
+ "Content-Type": "application/json",
665
+ "X-Project-Scope": projectScope
666
+ },
667
+ body: JSON.stringify({
668
+ project_scope: projectScope,
669
+ platform
670
+ })
671
+ });
672
+ }
673
+ async refreshToken(refreshToken) {
674
+ return this.flow.refreshToken(refreshToken);
675
+ }
676
+ async revokeToken(token, tokenType = "access_token") {
677
+ return this.flow.revokeToken(token, tokenType);
678
+ }
679
+ async validateToken(token) {
680
+ const trimmed = typeof token === "string" ? token.trim() : "";
681
+ if (!trimmed) {
682
+ return { valid: false, error: "Token is required" };
683
+ }
684
+ if (API_KEY_PREFIXES.some((prefix) => trimmed.startsWith(prefix))) {
685
+ return this.verifyApiKey(trimmed);
686
+ }
687
+ if (trimmed.startsWith("cli_") || trimmed.includes(".")) {
688
+ return this.verifyToken(trimmed);
689
+ }
690
+ return this.introspectToken(trimmed);
691
+ }
692
+ async verifyApiKey(apiKey) {
693
+ try {
694
+ const data = await this.requestJson("/v1/auth/verify-api-key", {
695
+ method: "POST",
696
+ headers: {
697
+ "Content-Type": "application/json",
698
+ "X-API-Key": apiKey
699
+ }
700
+ });
701
+ if (!data || data.valid === false) {
702
+ return {
703
+ valid: false,
704
+ type: "api_key",
705
+ error: data && (data.error || data.message) || "Invalid API key",
706
+ raw: data
707
+ };
708
+ }
709
+ return {
710
+ valid: true,
711
+ type: "api_key",
712
+ userId: data.userId,
713
+ projectScope: data.projectScope,
714
+ permissions: data.permissions || [],
715
+ raw: data
716
+ };
717
+ } catch (error) {
718
+ return {
719
+ valid: false,
720
+ type: "api_key",
721
+ error: error?.message || "API key validation failed",
722
+ raw: error?.data
723
+ };
724
+ }
725
+ }
726
+ async verifyToken(token) {
727
+ try {
728
+ const data = await this.requestJson("/v1/auth/verify-token", {
729
+ method: "POST",
730
+ headers: { "Content-Type": "application/json" },
731
+ body: JSON.stringify({ token })
732
+ });
733
+ if (!data || data.valid === false) {
734
+ return {
735
+ valid: false,
736
+ type: data?.type ? this.normalizeTokenType(data.type) : "jwt",
737
+ error: data?.error || "Invalid token",
738
+ raw: data
739
+ };
740
+ }
741
+ return {
742
+ valid: true,
743
+ type: data.type ? this.normalizeTokenType(data.type) : "jwt",
744
+ userId: data.user?.id,
745
+ email: data.user?.email,
746
+ role: data.user?.role,
747
+ expiresAt: data.expires_at || null,
748
+ raw: data
749
+ };
750
+ } catch (error) {
751
+ return {
752
+ valid: false,
753
+ type: "jwt",
754
+ error: error?.message || "Token verification failed",
755
+ raw: error?.data
756
+ };
757
+ }
758
+ }
759
+ async introspectToken(token) {
760
+ try {
761
+ const data = await this.requestJson("/oauth/introspect", {
762
+ method: "POST",
763
+ headers: { "Content-Type": "application/json" },
764
+ body: JSON.stringify({ token })
765
+ });
766
+ if (!data || data.active !== true) {
767
+ return {
768
+ valid: false,
769
+ type: "oauth",
770
+ error: "Token is inactive",
771
+ raw: data
772
+ };
773
+ }
774
+ return {
775
+ valid: true,
776
+ type: "oauth",
777
+ userId: data.user_id || data.sub,
778
+ scope: data.scope,
779
+ expiresAt: data.exp ? new Date(data.exp * 1e3).toISOString() : null,
780
+ raw: data
781
+ };
782
+ } catch (error) {
783
+ return {
784
+ valid: false,
785
+ type: "oauth",
786
+ error: error?.message || "Token introspection failed",
787
+ raw: error?.data
788
+ };
789
+ }
790
+ }
791
+ normalizeTokenType(type) {
792
+ if (type === "cli_token") return "cli";
793
+ if (type === "jwt") return "jwt";
794
+ return "jwt";
795
+ }
796
+ async requestJson(path, options) {
797
+ const response = await fetch4(`${this.authBaseUrl}${path.startsWith("/") ? path : `/${path}`}`, options);
798
+ const text = await response.text();
799
+ let data = null;
800
+ if (text) {
801
+ try {
802
+ data = JSON.parse(text);
803
+ } catch (parseError) {
804
+ data = { raw: text };
805
+ }
806
+ }
807
+ if (!response.ok) {
808
+ const message = data?.message || data?.error || `Request failed (${response.status})`;
809
+ const error = new Error(message);
810
+ error.status = response.status;
811
+ error.data = data;
812
+ throw error;
813
+ }
814
+ return data;
815
+ }
816
+ };
817
+
632
818
  // src/storage/api-key-storage-web.ts
633
819
  var ApiKeyStorageWeb = class {
634
820
  constructor() {
@@ -760,6 +946,7 @@ var ApiKeyStorageWeb = class {
760
946
  };
761
947
  export {
762
948
  ApiKeyStorageWeb,
949
+ AuthGatewayClient,
763
950
  BaseOAuthFlow,
764
951
  DesktopOAuthFlow,
765
952
  MCPClient,