Skip to content

GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE ignored when credentials.enc exists (inverts documented precedence) #857

Description

@rndmcnlly

Summary

On 0.22.5, when an encrypted credentials.enc exists in the config dir, setting GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE has no effect: API calls authenticate as the encrypted-credential account, not the account in the file. This inverts the documented precedence.

AGENTS.md and the README both state that CREDENTIALS_FILE takes precedence over encrypted credentials, with encrypted credentials being the fallback only when the env var is unset:

GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE | Path to OAuth credentials JSON (no default; if unset, falls back to encrypted credentials in ~/.config/gws/)

(README precedence table: GOOGLE_WORKSPACE_CLI_TOKEN = priority 1, GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE = priority 2, encrypted credentials = priority 3.)

Observed precedence is the reverse for priorities 2 vs 3: the encrypted store wins whenever credentials.enc is present, even with CREDENTIALS_FILE explicitly set.

Reproduction

Controlled A/B in an isolated config dir, varying only the presence of credentials.enc. Two distinct accounts (call them A and B); credentials.enc is account A, the credentials file is account B.

# Case 1: config dir has a credentials.enc (account A), written by `gws auth login`
GOOGLE_WORKSPACE_CLI_CONFIG_DIR=/tmp/dir-with-enc \
GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=/path/to/accountB-creds.json \
  gws drive about get --params '{"fields":"user(emailAddress)"}'
# => returns account A's email   (CREDENTIALS_FILE ignored)

# Case 2: identical, but config dir has NO credentials.enc
GOOGLE_WORKSPACE_CLI_CONFIG_DIR=/tmp/dir-without-enc \
GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=/path/to/accountB-creds.json \
  gws drive about get --params '{"fields":"user(emailAddress)"}'
# => returns account B's email   (CREDENTIALS_FILE honored, correct)
credentials.enc present CREDENTIALS_FILE set Identity returned
yes yes (account B) account A (wrong)
no yes (account B) account B (correct)

The only difference between the two runs is whether credentials.enc exists. The credentials file is well-formed (type: authorized_user with a valid refresh_token); Case 2 proves it loads and authenticates correctly in isolation. This was reproduced from a freshly gws auth login-written credentials.enc in a pristine GOOGLE_WORKSPACE_CLI_CONFIG_DIR, so it is not stale/migration state.

Expected vs actual

  • Expected (per docs): with CREDENTIALS_FILE set, it wins; credentials.enc is only the fallback when the var is unset.
  • Actual: credentials.enc shadows CREDENTIALS_FILE.

Impact

This is the documented multi-account story: a user with a logged-in default account cannot select an alternate account via CREDENTIALS_FILE, because the default's credentials.enc always wins. The only reliable workaround is an isolated GOOGLE_WORKSPACE_CLI_CONFIG_DIR per account (which has no credentials.enc to shadow the file). Worth noting the failure is silent: it returns another account's data with a 200, rather than erroring, which is a sharp edge for agent use.

Environment

  • gws 0.22.5 (Homebrew googleworkspace-cli 0.22.5, macOS arm64)
  • keyring backend (default)

Possible locus

Credential-source selection likely consults the encrypted store before checking the GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE env var (auth.rs / credential_store.rs). The TOKEN (priority 1) path was not tested here.


Filed by an agent (Claude Opus 4.8 via opencode) and verified by a human (the clean-room A/B repro above was run interactively). ✨

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions