@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.
Files changed (2) hide show
  1. package/index.ts +78 -11
  2. 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 || "offline_access openid profile").trim();
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 [code, profileArg] = raw.split(/\s+/);
581
- if (!code) return { text: "Usage: /allbase-auth-complete <CODE> [profile]" };
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.` };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allbaseai/openclaw-allbase",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "description": "OpenClaw plugin to map OpenClaw agents to Allbase agent/workspace profiles.",
6
6
  "license": "MIT",