@allbaseai/openclaw-allbase 0.1.4 → 0.1.5
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/index.ts +78 -11
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -130,7 +130,7 @@ function writeOAuthProfileToConfig(
|
|
|
130
130
|
cfg.profiles = cfg.profiles || {};
|
|
131
131
|
cfg.profiles[profileName] = {
|
|
132
132
|
...(cfg.profiles[profileName] || {}),
|
|
133
|
-
oauthAccessToken: values.oauthAccessToken,
|
|
133
|
+
...(values.oauthAccessToken ? { oauthAccessToken: values.oauthAccessToken } : {}),
|
|
134
134
|
...(values.oauthRefreshToken ? { oauthRefreshToken: values.oauthRefreshToken } : {}),
|
|
135
135
|
oauthClientId: values.oauthClientId,
|
|
136
136
|
oauthTokenEndpoint: values.oauthTokenEndpoint,
|
|
@@ -233,6 +233,67 @@ function jwtExpMs(token: string): number | null {
|
|
|
233
233
|
return null;
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
async function ensureOAuthClientId(
|
|
239
|
+
profileName: string,
|
|
240
|
+
baseUrl: string,
|
|
241
|
+
profile: AllbaseProfile,
|
|
242
|
+
redirectUri: string,
|
|
243
|
+
): Promise<{ clientId: string; tokenEndpoint: string; registrationEndpoint: string }> {
|
|
244
|
+
const existingClientId = (profile.oauthClientId || process.env.ALLBASE_OAUTH_CLIENT_ID || '').trim();
|
|
245
|
+
const tokenEndpoint = (profile.oauthTokenEndpoint || process.env.ALLBASE_OAUTH_TOKEN_ENDPOINT || `${baseUrl}/oauth/token`).trim();
|
|
246
|
+
|
|
247
|
+
// discover registration endpoint
|
|
248
|
+
let registrationEndpoint = `${baseUrl}/oauth/register`;
|
|
249
|
+
try {
|
|
250
|
+
const d = await fetch(`${baseUrl}/.well-known/oauth-authorization-server`);
|
|
251
|
+
if (d.ok) {
|
|
252
|
+
const doc = await d.json() as any;
|
|
253
|
+
if (typeof doc?.registration_endpoint === 'string' && doc.registration_endpoint.trim()) {
|
|
254
|
+
registrationEndpoint = doc.registration_endpoint.trim();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
} catch {
|
|
258
|
+
// use default
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (existingClientId) {
|
|
262
|
+
return { clientId: existingClientId, tokenEndpoint, registrationEndpoint };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const resp = await fetch(registrationEndpoint, {
|
|
266
|
+
method: 'POST',
|
|
267
|
+
headers: { 'Content-Type': 'application/json' },
|
|
268
|
+
body: JSON.stringify({
|
|
269
|
+
client_name: 'OpenClaw Allbase Plugin',
|
|
270
|
+
redirect_uris: [redirectUri],
|
|
271
|
+
grant_types: ['authorization_code', 'refresh_token'],
|
|
272
|
+
response_types: ['code'],
|
|
273
|
+
scope: 'allbase:read allbase:write',
|
|
274
|
+
token_endpoint_auth_method: 'none',
|
|
275
|
+
client_uri: 'https://docs.openclaw.ai',
|
|
276
|
+
}),
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
const text = await resp.text();
|
|
280
|
+
let body: any = {};
|
|
281
|
+
try { body = text ? JSON.parse(text) : {}; } catch { body = { raw: text }; }
|
|
282
|
+
if (!resp.ok || !body?.client_id) {
|
|
283
|
+
throw new Error(`OAuth client registration failed (${resp.status}): ${typeof body === 'string' ? body : JSON.stringify(body)}`);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const clientId = String(body.client_id);
|
|
287
|
+
writeOAuthProfileToConfig(profileName, {
|
|
288
|
+
oauthAccessToken: profile.oauthAccessToken || '',
|
|
289
|
+
oauthRefreshToken: profile.oauthRefreshToken,
|
|
290
|
+
oauthClientId: clientId,
|
|
291
|
+
oauthTokenEndpoint: tokenEndpoint,
|
|
292
|
+
baseUrl,
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
return { clientId, tokenEndpoint, registrationEndpoint };
|
|
296
|
+
}
|
|
236
297
|
async function getOAuthToken(baseUrl: string, profile: AllbaseProfile): Promise<{ token: string; exp: number }> {
|
|
237
298
|
const directToken = profile.oauthAccessToken?.trim();
|
|
238
299
|
if (directToken) {
|
|
@@ -517,15 +578,10 @@ const plugin = {
|
|
|
517
578
|
const cfg = getConfig(api);
|
|
518
579
|
const profile = (cfg.profiles || {})[profileName] || {};
|
|
519
580
|
const baseUrl = resolveBaseUrl(cfg, profile);
|
|
520
|
-
const clientId = (profile.oauthClientId || process.env.ALLBASE_OAUTH_CLIENT_ID || "").trim();
|
|
521
|
-
if (!clientId) {
|
|
522
|
-
return { text: "Missing oauthClientId. Set it in plugins.entries.openclaw-allbase.config.profiles.<profile>.oauthClientId or ALLBASE_OAUTH_CLIENT_ID." };
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
const tokenEndpoint = (profile.oauthTokenEndpoint || `${baseUrl}/oauth/token`).trim();
|
|
526
|
-
const authorizeEndpoint = `${baseUrl}/oauth/authorize`;
|
|
527
581
|
const redirectUri = (process.env.ALLBASE_OAUTH_REDIRECT_URI || "urn:ietf:wg:oauth:2.0:oob").trim();
|
|
528
|
-
const scope = (profile.oauthScope || process.env.ALLBASE_OAUTH_SCOPE || "
|
|
582
|
+
const scope = (profile.oauthScope || process.env.ALLBASE_OAUTH_SCOPE || "allbase:read allbase:write").trim();
|
|
583
|
+
const { clientId, tokenEndpoint } = await ensureOAuthClientId(profileName, baseUrl, profile, redirectUri);
|
|
584
|
+
const authorizeEndpoint = `${baseUrl}/oauth/authorize`;
|
|
529
585
|
const state = base64Url(randomBytes(24));
|
|
530
586
|
const codeVerifier = base64Url(randomBytes(48));
|
|
531
587
|
const codeChallenge = base64Url(createHash('sha256').update(codeVerifier).digest());
|
|
@@ -577,9 +633,20 @@ const plugin = {
|
|
|
577
633
|
handler: async (cmdCtx) => {
|
|
578
634
|
try {
|
|
579
635
|
const raw = (cmdCtx.args || "").trim();
|
|
580
|
-
const [
|
|
581
|
-
if (!
|
|
636
|
+
const [codeOrUrl, profileArg] = raw.split(/\s+/);
|
|
637
|
+
if (!codeOrUrl) return { text: "Usage: /allbase-auth-complete <CODE|CALLBACK_URL> [profile]" };
|
|
582
638
|
const profileName = profileArg || "default";
|
|
639
|
+
let code = codeOrUrl;
|
|
640
|
+
if (codeOrUrl.includes("code=") || codeOrUrl.startsWith("http")) {
|
|
641
|
+
try {
|
|
642
|
+
const u = new URL(codeOrUrl);
|
|
643
|
+
const c = u.searchParams.get("code");
|
|
644
|
+
if (c) code = c;
|
|
645
|
+
} catch {
|
|
646
|
+
const m = codeOrUrl.match(/[?&]code=([^&]+)/);
|
|
647
|
+
if (m?.[1]) code = decodeURIComponent(m[1]);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
583
650
|
const store = readOAuthStore();
|
|
584
651
|
const pending = store.pending?.[profileName];
|
|
585
652
|
if (!pending) return { text: `No pending OAuth flow for profile '${profileName}'. Run /allbase-auth-start ${profileName} first.` };
|