@openziti/ziti-mcp-server 0.6.0 → 0.8.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.
- package/README.md +129 -34
- package/dist/auth/client-credentials-flow.js +32 -13
- package/dist/auth/client-credentials-flow.js.map +1 -1
- package/dist/auth/device-auth-flow.d.ts +5 -36
- package/dist/auth/device-auth-flow.js +105 -84
- package/dist/auth/device-auth-flow.js.map +1 -1
- package/dist/auth/oidc-discovery.d.ts +51 -0
- package/dist/auth/oidc-discovery.js +100 -0
- package/dist/auth/oidc-discovery.js.map +1 -0
- package/dist/clients/base.js +18 -5
- package/dist/clients/base.js.map +1 -1
- package/dist/clients/claude.d.ts +6 -3
- package/dist/clients/claude.js +41 -8
- package/dist/clients/claude.js.map +1 -1
- package/dist/commands/init.d.ts +6 -29
- package/dist/commands/init.js +61 -50
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/logout.js +1 -1
- package/dist/commands/logout.js.map +1 -1
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/dist/utils/authenticated-client.js +2 -2
- package/dist/utils/authenticated-client.js.map +1 -1
- package/dist/utils/config.d.ts +7 -7
- package/dist/utils/config.js +7 -7
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/constants.d.ts +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/fabric-authenticated-client.js +2 -2
- package/dist/utils/fabric-authenticated-client.js.map +1 -1
- package/dist/utils/http-utility.js +5 -3
- package/dist/utils/http-utility.js.map +1 -1
- package/dist/utils/keychain.d.ts +4 -4
- package/dist/utils/keychain.js +3 -3
- package/dist/utils/keychain.js.map +1 -1
- package/dist/utils/logger.js +5 -5
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/terminal.js +6 -10
- package/dist/utils/terminal.js.map +1 -1
- package/dist/utils/types.d.ts +1 -0
- package/package.json +4 -5
- package/dist/utils/auth0-client.d.ts +0 -27
- package/dist/utils/auth0-client.js +0 -67
- package/dist/utils/auth0-client.js.map +0 -1
|
@@ -4,21 +4,42 @@ import { startSpinner, stopSpinner, getTenantFromToken, cliOutput, promptForBrow
|
|
|
4
4
|
import { log, logError } from '../utils/logger.js';
|
|
5
5
|
import { keychain } from '../utils/keychain.js';
|
|
6
6
|
import { DEFAULT_SCOPES } from '../utils/scopes.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
import { fetchOIDCDiscoveryDocument, getTokenEndpoint, getRevocationEndpoint, } from './oidc-discovery.js';
|
|
8
|
+
function buildConfig(selectedScopes, idpDomain, idpClientId, idpAudience) {
|
|
9
|
+
if (!idpDomain) {
|
|
10
|
+
throw new Error('IdP domain is required. Please provide --idp-domain parameter.');
|
|
11
|
+
}
|
|
12
|
+
if (!idpClientId) {
|
|
13
|
+
throw new Error('IdP client ID is required. Please provide --idp-client-id parameter.');
|
|
14
|
+
}
|
|
10
15
|
const scopes = selectedScopes && selectedScopes.length > 0
|
|
11
16
|
? selectedScopes.join(' ')
|
|
12
17
|
: DEFAULT_SCOPES.join(' ');
|
|
13
18
|
return {
|
|
14
|
-
|
|
15
|
-
clientId: idpClientId
|
|
16
|
-
audience: idpAudience
|
|
19
|
+
idpDomain,
|
|
20
|
+
clientId: idpClientId,
|
|
21
|
+
audience: idpAudience,
|
|
17
22
|
scopes,
|
|
18
23
|
};
|
|
19
24
|
}
|
|
20
25
|
async function requestAuthorization(selectedScopes, idpDomain, idpClientId, idpAudience) {
|
|
21
|
-
const config =
|
|
26
|
+
const config = buildConfig(selectedScopes, idpDomain, idpClientId, idpAudience);
|
|
27
|
+
// Fetch OIDC discovery document to get endpoints
|
|
28
|
+
log(`Discovering OIDC endpoints for ${config.idpDomain}...`);
|
|
29
|
+
let discovery;
|
|
30
|
+
try {
|
|
31
|
+
discovery = await fetchOIDCDiscoveryDocument(config.idpDomain);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
logError('Failed to fetch OIDC discovery document:', error);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
const deviceAuthEndpoint = discovery.device_authorization_endpoint;
|
|
38
|
+
if (!deviceAuthEndpoint) {
|
|
39
|
+
logError('Error', `IdP ${config.idpDomain} does not support device authorization flow. ` +
|
|
40
|
+
'The device_authorization_endpoint is not present in the discovery document.');
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
22
43
|
const body = {
|
|
23
44
|
client_id: config.clientId,
|
|
24
45
|
};
|
|
@@ -29,7 +50,8 @@ async function requestAuthorization(selectedScopes, idpDomain, idpClientId, idpA
|
|
|
29
50
|
body.scope = config.scopes;
|
|
30
51
|
}
|
|
31
52
|
try {
|
|
32
|
-
|
|
53
|
+
log(`Requesting device code from ${deviceAuthEndpoint}`);
|
|
54
|
+
const response = await fetch(deviceAuthEndpoint, {
|
|
33
55
|
method: 'POST',
|
|
34
56
|
body: new URLSearchParams(body),
|
|
35
57
|
headers: {
|
|
@@ -40,10 +62,10 @@ async function requestAuthorization(selectedScopes, idpDomain, idpClientId, idpA
|
|
|
40
62
|
const jsonRes = await response.json();
|
|
41
63
|
if (!jsonRes.error) {
|
|
42
64
|
cliOutput(`\nVerify this code on screen: ${chalk.bold.green(jsonRes.user_code)}\n`);
|
|
43
|
-
|
|
65
|
+
cliOutput(`\nVerify at this URL: ${chalk.bold.green(jsonRes.verification_uri_complete || jsonRes.verification_uri)}\n`);
|
|
44
66
|
await promptForBrowserPermission();
|
|
45
|
-
openBrowser(jsonRes.verification_uri_complete);
|
|
46
|
-
await exchangeDeviceCodeForToken(jsonRes,
|
|
67
|
+
openBrowser(jsonRes.verification_uri_complete || jsonRes.verification_uri);
|
|
68
|
+
await exchangeDeviceCodeForToken(jsonRes, config, discovery.token_endpoint);
|
|
47
69
|
}
|
|
48
70
|
else {
|
|
49
71
|
logError('Error', jsonRes);
|
|
@@ -61,7 +83,6 @@ function wait(ms) {
|
|
|
61
83
|
function isValidUrl(url) {
|
|
62
84
|
try {
|
|
63
85
|
const parsedUrl = new URL(url);
|
|
64
|
-
// Check for safe protocols
|
|
65
86
|
return ['http:', 'https:'].includes(parsedUrl.protocol);
|
|
66
87
|
}
|
|
67
88
|
catch (error) {
|
|
@@ -82,48 +103,62 @@ function openBrowser(url) {
|
|
|
82
103
|
logError('Failed to open browser:', err);
|
|
83
104
|
});
|
|
84
105
|
}
|
|
85
|
-
async function exchangeDeviceCodeForToken(deviceCode,
|
|
86
|
-
|
|
87
|
-
startSpinner('Waiting for authorization...');
|
|
106
|
+
async function exchangeDeviceCodeForToken(deviceCode, config, tokenEndpoint) {
|
|
107
|
+
startSpinner('\nWaiting for authorization...\n');
|
|
88
108
|
while (true) {
|
|
109
|
+
await wait(deviceCode.interval * 1000);
|
|
89
110
|
try {
|
|
90
|
-
|
|
111
|
+
log(`Polling token endpoint: ${tokenEndpoint}`);
|
|
112
|
+
const response = await fetch(tokenEndpoint, {
|
|
91
113
|
method: 'POST',
|
|
92
|
-
body: new URLSearchParams({
|
|
93
|
-
client_id: config.clientId,
|
|
94
|
-
device_code: deviceCode.device_code,
|
|
95
|
-
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
96
|
-
}),
|
|
97
114
|
headers: {
|
|
98
115
|
Accept: 'application/json',
|
|
99
116
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
100
117
|
},
|
|
118
|
+
body: new URLSearchParams({
|
|
119
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
120
|
+
device_code: deviceCode.device_code,
|
|
121
|
+
client_id: config.clientId,
|
|
122
|
+
}),
|
|
101
123
|
});
|
|
102
124
|
const jsonRes = await response.json();
|
|
103
125
|
if (!jsonRes.error) {
|
|
104
|
-
|
|
105
|
-
|
|
126
|
+
await storeTokens(jsonRes);
|
|
127
|
+
stopSpinner();
|
|
128
|
+
cliOutput(`\n${chalk.green('✓')} Successfully authenticated!\n`);
|
|
129
|
+
break;
|
|
106
130
|
}
|
|
107
131
|
else if (['authorization_pending', 'slow_down'].includes(jsonRes.error)) {
|
|
108
|
-
|
|
132
|
+
// Continue polling - user hasn't authorized yet
|
|
133
|
+
if (jsonRes.error === 'slow_down') {
|
|
134
|
+
await wait(deviceCode.interval * 1000);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else if (jsonRes.error === 'access_denied') {
|
|
138
|
+
stopSpinner();
|
|
139
|
+
logError('Access denied:', jsonRes.error_description || 'User denied authorization or IdP configuration issue');
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
else if (jsonRes.error === 'expired_token') {
|
|
143
|
+
stopSpinner();
|
|
144
|
+
logError('Device code expired:', 'Please try again');
|
|
145
|
+
break;
|
|
109
146
|
}
|
|
110
147
|
else {
|
|
111
148
|
stopSpinner();
|
|
112
|
-
logError('Unexpected error:', jsonRes.error);
|
|
113
|
-
break;
|
|
149
|
+
logError('Unexpected error:', `${jsonRes.error}: ${jsonRes.error_description || ''}`);
|
|
150
|
+
break;
|
|
114
151
|
}
|
|
115
152
|
}
|
|
116
153
|
catch (err) {
|
|
117
154
|
stopSpinner();
|
|
118
155
|
logError('Error in token exchange:', err);
|
|
119
|
-
break;
|
|
156
|
+
break;
|
|
120
157
|
}
|
|
121
158
|
}
|
|
122
|
-
stopSpinner();
|
|
123
159
|
}
|
|
124
|
-
async function
|
|
160
|
+
async function storeTokens(tokenSet) {
|
|
125
161
|
const tenantName = getTenantFromToken(tokenSet.access_token);
|
|
126
|
-
// Store tokens in keychain
|
|
127
162
|
await keychain.setToken(tokenSet.access_token);
|
|
128
163
|
await keychain.setDomain(tenantName);
|
|
129
164
|
if (tokenSet.refresh_token) {
|
|
@@ -136,7 +171,7 @@ async function fetchUserInfo(tokenSet) {
|
|
|
136
171
|
log(`Token expires at: ${new Date(expiresAt).toISOString()}`);
|
|
137
172
|
}
|
|
138
173
|
}
|
|
139
|
-
export async function refreshAccessToken(
|
|
174
|
+
export async function refreshAccessToken(idpDomain, idpClientId) {
|
|
140
175
|
try {
|
|
141
176
|
log('Attempting to refresh access token');
|
|
142
177
|
const refreshToken = await keychain.getRefreshToken();
|
|
@@ -144,12 +179,22 @@ export async function refreshAccessToken(selectedScopes) {
|
|
|
144
179
|
log('No refresh token found in keychain');
|
|
145
180
|
return null;
|
|
146
181
|
}
|
|
147
|
-
|
|
148
|
-
const
|
|
182
|
+
// Get IdP domain from keychain if not provided
|
|
183
|
+
const domain = idpDomain || (await keychain.getDomain());
|
|
184
|
+
if (!domain) {
|
|
185
|
+
log('No IdP domain available for token refresh');
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
if (!idpClientId) {
|
|
189
|
+
log('Client ID is required for token refresh');
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
const tokenEndpoint = await getTokenEndpoint(domain);
|
|
193
|
+
const response = await fetch(tokenEndpoint, {
|
|
149
194
|
method: 'POST',
|
|
150
195
|
body: new URLSearchParams({
|
|
151
196
|
grant_type: 'refresh_token',
|
|
152
|
-
client_id:
|
|
197
|
+
client_id: idpClientId,
|
|
153
198
|
refresh_token: refreshToken,
|
|
154
199
|
}),
|
|
155
200
|
headers: {
|
|
@@ -161,17 +206,7 @@ export async function refreshAccessToken(selectedScopes) {
|
|
|
161
206
|
log(`Error refreshing token: ${tokenSet.error}`);
|
|
162
207
|
return null;
|
|
163
208
|
}
|
|
164
|
-
|
|
165
|
-
const tenantName = getTenantFromToken(tokenSet.access_token);
|
|
166
|
-
await keychain.setToken(tokenSet.access_token);
|
|
167
|
-
await keychain.setDomain(tenantName);
|
|
168
|
-
if (tokenSet.refresh_token) {
|
|
169
|
-
await keychain.setRefreshToken(tokenSet.refresh_token);
|
|
170
|
-
}
|
|
171
|
-
if (tokenSet.expires_in) {
|
|
172
|
-
const expiresAt = Date.now() + tokenSet.expires_in * 1000;
|
|
173
|
-
await keychain.setTokenExpiresAt(expiresAt);
|
|
174
|
-
}
|
|
209
|
+
await storeTokens(tokenSet);
|
|
175
210
|
log('Successfully refreshed access token');
|
|
176
211
|
return tokenSet.access_token;
|
|
177
212
|
}
|
|
@@ -181,11 +216,10 @@ export async function refreshAccessToken(selectedScopes) {
|
|
|
181
216
|
}
|
|
182
217
|
}
|
|
183
218
|
/**
|
|
184
|
-
* Revokes the refresh token
|
|
185
|
-
* Returns true if
|
|
186
|
-
* @returns {Promise<boolean>}
|
|
219
|
+
* Revokes the refresh token stored in the keychain.
|
|
220
|
+
* Returns true if successful or if no refresh token exists.
|
|
187
221
|
*/
|
|
188
|
-
export async function revokeRefreshToken() {
|
|
222
|
+
export async function revokeRefreshToken(idpDomain, idpClientId) {
|
|
189
223
|
try {
|
|
190
224
|
log('Attempting to revoke refresh token');
|
|
191
225
|
const refreshToken = await keychain.getRefreshToken();
|
|
@@ -193,23 +227,40 @@ export async function revokeRefreshToken() {
|
|
|
193
227
|
log('No refresh token found in keychain');
|
|
194
228
|
return true;
|
|
195
229
|
}
|
|
196
|
-
const
|
|
197
|
-
|
|
230
|
+
const domain = idpDomain || (await keychain.getDomain());
|
|
231
|
+
if (!domain) {
|
|
232
|
+
log('No IdP domain available for token revocation');
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
if (!idpClientId) {
|
|
236
|
+
log('Client ID is required for token revocation');
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
const revocationEndpoint = await getRevocationEndpoint(domain);
|
|
240
|
+
if (!revocationEndpoint) {
|
|
241
|
+
log(`IdP ${domain} does not support token revocation`);
|
|
242
|
+
// Consider this a success since we can't revoke anyway
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
const response = await fetch(revocationEndpoint, {
|
|
198
246
|
method: 'POST',
|
|
199
247
|
body: new URLSearchParams({
|
|
200
|
-
client_id:
|
|
248
|
+
client_id: idpClientId,
|
|
201
249
|
token: refreshToken,
|
|
202
250
|
}),
|
|
203
251
|
headers: {
|
|
204
252
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
205
253
|
},
|
|
206
254
|
});
|
|
255
|
+
// RFC 7009: The authorization server responds with HTTP status code 200
|
|
256
|
+
// if the token has been revoked successfully or if the client submitted
|
|
257
|
+
// an invalid token.
|
|
207
258
|
if (response.status === 200) {
|
|
208
259
|
log('Refresh token successfully revoked');
|
|
209
260
|
return true;
|
|
210
261
|
}
|
|
211
262
|
else {
|
|
212
|
-
log('Error calling revoke API:
|
|
263
|
+
log('Error calling revoke API:', response.statusText);
|
|
213
264
|
return false;
|
|
214
265
|
}
|
|
215
266
|
}
|
|
@@ -220,23 +271,6 @@ export async function revokeRefreshToken() {
|
|
|
220
271
|
}
|
|
221
272
|
/**
|
|
222
273
|
* Determines if the current access token is expired or will expire soon.
|
|
223
|
-
*
|
|
224
|
-
* This security check is crucial for maintaining continuous authenticated access
|
|
225
|
-
* to Auth0 APIs. It includes a configurable buffer time to proactively detect
|
|
226
|
-
* tokens that will expire soon, preventing potential disruptions during operations
|
|
227
|
-
* that might span multiple API calls. This proactive approach allows the system to
|
|
228
|
-
* initiate refresh flows before actual expiration occurs.
|
|
229
|
-
*
|
|
230
|
-
* The function considers a token expired in the following cases:
|
|
231
|
-
* - No expiration time is found in the keychain via `keychain.getTokenExpiresAt()`
|
|
232
|
-
* - Current time + buffer exceeds the token's expiration time
|
|
233
|
-
* - Error occurs during expiration check (fails secure)
|
|
234
|
-
*
|
|
235
|
-
* This function is used both by `validateAuthorization()` in `run.ts` for user-friendly
|
|
236
|
-
* startup validation and by `validateConfig()` for continuous runtime validation.
|
|
237
|
-
*
|
|
238
|
-
* @param {number} bufferSeconds - Seconds before actual expiration to consider token expired (default: 300s/5min)
|
|
239
|
-
* @returns {Promise<boolean>} True if token is expired or will expire within the buffer period
|
|
240
274
|
*/
|
|
241
275
|
export async function isTokenExpired(bufferSeconds = 300) {
|
|
242
276
|
try {
|
|
@@ -258,20 +292,7 @@ export async function isTokenExpired(bufferSeconds = 300) {
|
|
|
258
292
|
}
|
|
259
293
|
}
|
|
260
294
|
/**
|
|
261
|
-
* Retrieves a valid access token for
|
|
262
|
-
*
|
|
263
|
-
* This function serves as the main entry point for credential retrieval,
|
|
264
|
-
* ensuring that only valid, non-expired tokens are provided to API operations.
|
|
265
|
-
* It implements a critical security checkpoint that prevents operations from
|
|
266
|
-
* proceeding with invalid authentication, which could lead to API failures
|
|
267
|
-
* or unpredictable behavior.
|
|
268
|
-
*
|
|
269
|
-
* The function performs these key security checks:
|
|
270
|
-
* 1. Verifies token expiration status using isTokenExpired
|
|
271
|
-
* 2. Provides clear guidance to users when re-authentication is needed
|
|
272
|
-
* 3. Handles errors gracefully with a fail-secure approach
|
|
273
|
-
*
|
|
274
|
-
* @returns {Promise<string|null>} A valid access token, or null if no valid token is available
|
|
295
|
+
* Retrieves a valid access token for API operations.
|
|
275
296
|
*/
|
|
276
297
|
export async function getValidAccessToken() {
|
|
277
298
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-auth-flow.js","sourceRoot":"","sources":["../../src/auth/device-auth-flow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,SAAS,EACT,0BAA0B,GAC3B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"device-auth-flow.js","sourceRoot":"","sources":["../../src/auth/device-auth-flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OIDC Discovery document structure
|
|
3
|
+
* Based on OpenID Connect Discovery 1.0 specification
|
|
4
|
+
*/
|
|
5
|
+
export interface OIDCDiscoveryDocument {
|
|
6
|
+
issuer: string;
|
|
7
|
+
authorization_endpoint?: string;
|
|
8
|
+
token_endpoint: string;
|
|
9
|
+
userinfo_endpoint?: string;
|
|
10
|
+
jwks_uri?: string;
|
|
11
|
+
registration_endpoint?: string;
|
|
12
|
+
scopes_supported?: string[];
|
|
13
|
+
response_types_supported?: string[];
|
|
14
|
+
grant_types_supported?: string[];
|
|
15
|
+
subject_types_supported?: string[];
|
|
16
|
+
id_token_signing_alg_values_supported?: string[];
|
|
17
|
+
token_endpoint_auth_methods_supported?: string[];
|
|
18
|
+
revocation_endpoint?: string;
|
|
19
|
+
introspection_endpoint?: string;
|
|
20
|
+
device_authorization_endpoint?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Fetches the OIDC discovery document from an IdP
|
|
24
|
+
*
|
|
25
|
+
* @param idpDomain - The IdP domain (e.g., 'your-tenant.auth0.com' or 'accounts.google.com')
|
|
26
|
+
* @returns The OIDC discovery document
|
|
27
|
+
* @throws Error if the discovery document cannot be fetched
|
|
28
|
+
*/
|
|
29
|
+
export declare function fetchOIDCDiscoveryDocument(idpDomain: string): Promise<OIDCDiscoveryDocument>;
|
|
30
|
+
/**
|
|
31
|
+
* Gets the token endpoint from the IdP's discovery document
|
|
32
|
+
*/
|
|
33
|
+
export declare function getTokenEndpoint(idpDomain: string): Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Gets the device authorization endpoint from the IdP's discovery document
|
|
36
|
+
* @throws Error if the IdP doesn't support device authorization
|
|
37
|
+
*/
|
|
38
|
+
export declare function getDeviceAuthorizationEndpoint(idpDomain: string): Promise<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Gets the revocation endpoint from the IdP's discovery document
|
|
41
|
+
* @returns The revocation endpoint, or null if not supported
|
|
42
|
+
*/
|
|
43
|
+
export declare function getRevocationEndpoint(idpDomain: string): Promise<string | null>;
|
|
44
|
+
/**
|
|
45
|
+
* Checks if the IdP supports a specific grant type
|
|
46
|
+
*/
|
|
47
|
+
export declare function supportsGrantType(idpDomain: string, grantType: string): Promise<boolean>;
|
|
48
|
+
/**
|
|
49
|
+
* Clears the discovery cache (useful for testing or when IdP config changes)
|
|
50
|
+
*/
|
|
51
|
+
export declare function clearDiscoveryCache(): void;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { log, logError } from '../utils/logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* Cache for OIDC discovery documents to avoid repeated fetches
|
|
4
|
+
*/
|
|
5
|
+
const discoveryCache = new Map();
|
|
6
|
+
const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
7
|
+
/**
|
|
8
|
+
* Fetches the OIDC discovery document from an IdP
|
|
9
|
+
*
|
|
10
|
+
* @param idpDomain - The IdP domain (e.g., 'your-tenant.auth0.com' or 'accounts.google.com')
|
|
11
|
+
* @returns The OIDC discovery document
|
|
12
|
+
* @throws Error if the discovery document cannot be fetched
|
|
13
|
+
*/
|
|
14
|
+
export async function fetchOIDCDiscoveryDocument(idpDomain) {
|
|
15
|
+
// Check cache first
|
|
16
|
+
const cached = discoveryCache.get(idpDomain);
|
|
17
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
18
|
+
log(`Using cached OIDC discovery document for ${idpDomain}`);
|
|
19
|
+
return cached.document;
|
|
20
|
+
}
|
|
21
|
+
// Normalize domain - remove protocol if present
|
|
22
|
+
const normalizedDomain = idpDomain.replace(/^https?:\/\//, '');
|
|
23
|
+
const discoveryUrl = `https://${normalizedDomain}/.well-known/openid-configuration`;
|
|
24
|
+
log(`Fetching OIDC discovery document from ${discoveryUrl}`);
|
|
25
|
+
try {
|
|
26
|
+
const response = await fetch(discoveryUrl, {
|
|
27
|
+
method: 'GET',
|
|
28
|
+
headers: {
|
|
29
|
+
Accept: 'application/json',
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
if (!response.ok) {
|
|
33
|
+
throw new Error(`Failed to fetch OIDC discovery document: ${response.status} ${response.statusText}`);
|
|
34
|
+
}
|
|
35
|
+
const document = (await response.json());
|
|
36
|
+
// Validate required fields
|
|
37
|
+
if (!document.issuer) {
|
|
38
|
+
throw new Error('OIDC discovery document missing required field: issuer');
|
|
39
|
+
}
|
|
40
|
+
if (!document.token_endpoint) {
|
|
41
|
+
throw new Error('OIDC discovery document missing required field: token_endpoint');
|
|
42
|
+
}
|
|
43
|
+
// Cache the document
|
|
44
|
+
discoveryCache.set(idpDomain, {
|
|
45
|
+
document,
|
|
46
|
+
expiresAt: Date.now() + CACHE_TTL_MS,
|
|
47
|
+
});
|
|
48
|
+
log(`Successfully fetched OIDC discovery document for ${idpDomain}`);
|
|
49
|
+
return document;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
logError(`Error fetching OIDC discovery document from ${discoveryUrl}:`, error);
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Gets the token endpoint from the IdP's discovery document
|
|
58
|
+
*/
|
|
59
|
+
export async function getTokenEndpoint(idpDomain) {
|
|
60
|
+
const document = await fetchOIDCDiscoveryDocument(idpDomain);
|
|
61
|
+
return document.token_endpoint;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Gets the device authorization endpoint from the IdP's discovery document
|
|
65
|
+
* @throws Error if the IdP doesn't support device authorization
|
|
66
|
+
*/
|
|
67
|
+
export async function getDeviceAuthorizationEndpoint(idpDomain) {
|
|
68
|
+
const document = await fetchOIDCDiscoveryDocument(idpDomain);
|
|
69
|
+
if (!document.device_authorization_endpoint) {
|
|
70
|
+
throw new Error(`IdP ${idpDomain} does not support device authorization flow. ` +
|
|
71
|
+
'The device_authorization_endpoint is not present in the discovery document.');
|
|
72
|
+
}
|
|
73
|
+
return document.device_authorization_endpoint;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Gets the revocation endpoint from the IdP's discovery document
|
|
77
|
+
* @returns The revocation endpoint, or null if not supported
|
|
78
|
+
*/
|
|
79
|
+
export async function getRevocationEndpoint(idpDomain) {
|
|
80
|
+
const document = await fetchOIDCDiscoveryDocument(idpDomain);
|
|
81
|
+
return document.revocation_endpoint || null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Checks if the IdP supports a specific grant type
|
|
85
|
+
*/
|
|
86
|
+
export async function supportsGrantType(idpDomain, grantType) {
|
|
87
|
+
const document = await fetchOIDCDiscoveryDocument(idpDomain);
|
|
88
|
+
if (!document.grant_types_supported) {
|
|
89
|
+
// If not specified, assume common grant types are supported per OIDC spec
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
return document.grant_types_supported.includes(grantType);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Clears the discovery cache (useful for testing or when IdP config changes)
|
|
96
|
+
*/
|
|
97
|
+
export function clearDiscoveryCache() {
|
|
98
|
+
discoveryCache.clear();
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=oidc-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oidc-discovery.js","sourceRoot":"","sources":["../../src/auth/oidc-discovery.ts"],"names":[],"mappings":"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"}
|
package/dist/clients/base.js
CHANGED
|
@@ -60,15 +60,28 @@ export class BaseClientManager {
|
|
|
60
60
|
* @protected
|
|
61
61
|
*/
|
|
62
62
|
createServerConfig(options) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
let command;
|
|
64
|
+
let args;
|
|
65
|
+
if (options.wsl) {
|
|
66
|
+
const runCmd = [
|
|
67
|
+
'source ~/.nvm/nvm.sh',
|
|
68
|
+
`${entryPoint} run --tools '${options.tools.join(',')}'${options.readOnly ? ' --read-only' : ''}`,
|
|
69
|
+
].join(' && ');
|
|
70
|
+
command = 'wsl.exe';
|
|
71
|
+
args = ['bash', '-c', runCmd];
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
args = [entryPoint, 'run', '--tools', options.tools.join(',')];
|
|
75
|
+
if (options.readOnly) {
|
|
76
|
+
args.push('--read-only');
|
|
77
|
+
}
|
|
78
|
+
command = process.execPath;
|
|
66
79
|
}
|
|
67
80
|
const config = {
|
|
68
|
-
command
|
|
81
|
+
command,
|
|
69
82
|
args,
|
|
70
83
|
env: {
|
|
71
|
-
DEBUG: 'ziti-mcp',
|
|
84
|
+
DEBUG: 'ziti-mcp-server',
|
|
72
85
|
},
|
|
73
86
|
};
|
|
74
87
|
if (this.capabilities?.length) {
|
package/dist/clients/base.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/clients/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGjD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,2DAA2D;AAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAClD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;AAEtD;;;;GAIG;AACH,MAAM,OAAgB,iBAAiB;IAClB,UAAU,CAAa;IAC1B,WAAW,CAAS;IACjB,YAAY,CAAY;IAE3C;;;;OAIG;IACH,YAAY,OAAiF;QAC3F,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAC3C,CAAC;IAYD;;;;;;;OAOG;IACH,KAAK,CAAC,SAAS,CAAC,OAAsB;QACpC,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAC3C,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;QAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAEtD,UAAU,CAAC,eAAe,CAAC,GAAG,YAAY,CAAC;QAC3C,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;QAE/B,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACrC,GAAG,CAAC,WAAW,IAAI,CAAC,WAAW,oBAAoB,UAAU,EAAE,CAAC,CAAC;QAEjE,SAAS,CACP,KAAK,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,oCAAoC,KAAK,CAAC,MAAM,CACnE,WAAW,IAAI,CAAC,WAAW,EAAE,CAC9B,sBAAsB,CACxB,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;OAWG;IACO,kBAAkB,CAAC,OAAsB;QACjD,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/clients/base.ts"],"names":[],"mappings":"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"}
|
package/dist/clients/claude.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BaseClientManager } from './base.js';
|
|
2
|
+
import type { ClientOptions } from '../utils/types.js';
|
|
2
3
|
/**
|
|
3
4
|
* Client manager implementation for Claude Desktop.
|
|
4
5
|
*
|
|
@@ -8,13 +9,15 @@ import { BaseClientManager } from './base.js';
|
|
|
8
9
|
* @see {@link https://claude.ai/download | Claude Desktop Download}
|
|
9
10
|
*/
|
|
10
11
|
export declare class ClaudeClientManager extends BaseClientManager {
|
|
12
|
+
private wsl;
|
|
11
13
|
constructor();
|
|
14
|
+
configure(options: ClientOptions): Promise<void>;
|
|
12
15
|
/**
|
|
13
16
|
* Returns the path to the Claude Desktop configuration file.
|
|
14
17
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
+
* When running under WSL, resolves the Windows APPDATA path via cmd.exe and
|
|
19
|
+
* constructs the path under the WSL mount point so the config is placed where
|
|
20
|
+
* Claude Desktop (running on Windows) expects it.
|
|
18
21
|
*
|
|
19
22
|
* @returns The absolute path to the configuration file.
|
|
20
23
|
*/
|