Skip to content

feat(auth): use a lone BASE44_ACCESS_TOKEN as an in-memory credential - #681

Open
amitbardos wants to merge 5 commits into
mainfrom
amitb/env-token-in-memory
Open

amitbardos wants to merge 5 commits into
mainfrom
amitb/env-token-in-memory

Conversation

@amitbardos

@amitbardos amitbardos commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Note

Description

BASE44_ACCESS_TOKEN previously only did something when paired with BASE44_REFRESH_TOKEN — the pair was seeded into ~/.base44/auth/auth.json, and a lone access token was ignored entirely. This PR makes a lone access token usable as a process-scoped, in-memory credential, for callers like the MCP run_command tool that inject a short-lived token into a shared app sandbox for a single command. It is never written to disk, takes precedence over auth.json for that one process, and is only honored when it comes from the real process environment — not from a project .env/.env.local.

Related Issue

None

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Other (please describe):

Changes Made

  • core/auth/config.ts — seedAuthFromEnv() now splits the two cases. With a refresh token the behavior is unchanged (seed auth.json). Without one, a valid JWT (sub + exp required) is stored in a module-level envAccessTokenAuth for the current process only.
  • readAuth() returns the in-memory credential ahead of auth.json, so the lone token is the bearer for every request in that command.
  • refreshAndSaveTokens() returns null immediately when an env access token is active — there is nothing to refresh with, and auth.json belongs to someone else, so it is never refreshed, rewritten, or deleted. On expiry the 401 simply surfaces.
  • core/utils/env.ts — records whether BASE44_ACCESS_TOKEN (bare or BASE44_PROJECTS_-prefixed) was already in the ambient process env before dotenv ran, and exposes isAccessTokenFromEnvFile(). A token sourced from a project env file is rejected for this path, since it would otherwise silently authenticate every later command run in that directory.
  • infra/build-binaries.ts — compile the standalone binaries with --no-compile-autoload-dotenv. Bun autoloads .env into process.env before any CLI code runs, which would make a file-sourced token look ambient and defeat the check above. The CLI loads project env files itself, so nothing else changes.
  • docs/api-patterns.md — documents the lone-token path alongside the existing paired-credential seeding.
  • Tests — rewrote the "incomplete env credentials" case and added four: a lone token is used as the bearer and leaves auth.json byte-identical; a 401 triggers no refresh and no deletion; a token from a project .env is ignored; a JWT missing sub/exp is ignored. A follow-up commit mocks userinfo in the whoami cases, since whoami now verifies the session against the server (fix(auth): verify the session in whoami and fail fast on login without a TTY #688).

Testing

  • I have tested these changes locally
  • I have added/updated tests as needed
  • All tests pass (npm test)

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (if applicable)
  • My changes generate no new warnings
  • I have updated docs/ (AGENTS.md) if I made architectural changes

Additional Notes

Precedence is unchanged elsewhere: BASE44_API_KEY (workspace key) still wins, and the paired BASE44_ACCESS_TOKEN + BASE44_REFRESH_TOKEN seeding path behaves exactly as before. The security-relevant invariant is that a lone token never outlives its process and never touches an existing login — both directions are covered by tests. The lint, typecheck, build, and knip checks are green; the test matrix was still running when this description was generated, so the testing boxes above are left unchecked.


🤖 Generated by Claude | 2026-11-08 15:18 UTC | 965687f

When BASE44_ACCESS_TOKEN is set without BASE44_REFRESH_TOKEN (e.g. the MCP
run_command tool injecting a short-lived token into a shared app sandbox for
one command), hold it in memory for the current process only: readAuth()
returns it ahead of auth.json, it is never written to disk, and
refreshAndSaveTokens() returns null without refreshing, writing or deleting
auth.json, so on expiry the 401 surfaces. The paired access+refresh path and
BASE44_API_KEY precedence are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

🚀 Package Preview Available!


Install this PR's preview build with npm:

npm i @base44-preview/cli@0.3.1-pr.681.965687f

Prefer not to change any import paths? Install using npm alias so your code still imports base44:

npm i "base44@npm:@base44-preview/cli@0.3.1-pr.681.965687f"

Or add it to your package.json dependencies:

{
  "dependencies": {
    "base44": "npm:@base44-preview/cli@0.3.1-pr.681.965687f"
  }
}

Preview published to npm registry — try new features instantly!

amitbardos and others added 4 commits November 8, 2026 14:34
A token in a project .env or .env.local would otherwise authenticate every
later command in that directory, which defeats the per-command scope in a
shared sandbox. Tokens paired with a refresh token are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
whoami now verifies the session with the server (#688).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bun's standalone executable loads .env from the working directory before the
CLI starts, so a token from that file looked like process env. The CLI already
loads project env files itself, as the npm build does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@amitbardos
amitbardos enabled auto-merge (squash) November 9, 2026 15:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant