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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions