Forum Discussion

mondesign's avatar
mondesign
New Contributor
1 month ago

1Password CLI Service Account Bug Report

1Password CLI Service Account Bug Report

 

SUMMARY

Service account tokens fail with "Signin credentials are not compatible with the provided user auth from server" error when called from exec/automated contexts, but work from interactive shell on the same system.

 

ENVIRONMENT

OS: Ubuntu 25.10 (Questing Quokka)

Kernel: Linux 6.17.0-8-generic x86_64

1Password CLI Version: 2.32.1

Shell: bash

Service Account: Multiple tested (both fresh and rotated tokens)

Connect Server: Not running (confirmed via docker ps and process list)

 

ISSUE DESCRIPTION

 

Service account authentication fails consistently with this error:

[ERROR] 2026/02/05 15:16:50 Signin credentials are not compatible with the provided user auth from server

 

WHAT WORKS:

Interactive shell (as root) - export OP_SERVICE_ACCOUNT_TOKEN='ops_eyJ...' then op vault list returns vault list successfully

 

WHAT FAILS:

Same token, same user, via wrapper script or exec - /usr/local/bin/op-sa.sh vault list gives ERROR: Signin credentials are not compatible

 

Wrapper script (/usr/local/bin/op-sa.sh):

#!/usr/bin/env bash

unset OP_CONNECT_HOST

unset OP_CONNECT_TOKEN

unset OP_SESSION

export OP_SERVICE_ACCOUNT_TOKEN='ops_eyJ...'

exec /usr/bin/op "$@"

 

DIAGNOSTIC STEPS TAKEN

 

Environment comparison: Verified that OP_SERVICE_ACCOUNT_TOKEN is identical in both contexts. Interactive shell env shows correct token. Via wrapper bash -c 'env' shows identical token.

 

Cleared all op state multiple times: killall -9 op and rm -rf ~/.config/op ~/.op /run/user/0/op-daemon.*

 

Tested multiple service accounts: Original "Chris" account, rotated token for "Chris", and fresh "test" account. All fail with same error from wrapper/exec, all work from interactive shell.

 

Verified no Connect Server: No Docker containers running, no OP_CONNECT_* environment variables set, pure service account + CLI setup.

 

Token format verified: Single line (no newlines/wrapping), correct base64 encoding, no "illegal base64" errors.

 

CONFIGURATION FILES CHECKED

 

The file ~/.config/op/config gets recreated with device ID: {"latest_signin": "", "device": "bl6dyt5omziik2hw32myzslvje", "accounts": null}

 

The device ID in config differs from the deviceUuid embedded in the service account token, which might be causing the conflict.

 

EXPECTED BEHAVIOR

Service account tokens should authenticate successfully regardless of whether they're called from an interactive shell or an automated/exec context, as long as the OP_SERVICE_ACCOUNT_TOKEN environment variable is set correctly.

 

ACTUAL BEHAVIOR

Authentication fails with "Signin credentials are not compatible" error when called from non-interactive contexts, despite identical environment variables.

 

REPRODUCTION STEPS

Create a service account in 1Password web UI. Copy the service account token. Create wrapper script with token hardcoded (see above). Run: ./wrapper.sh vault list and observe error. Run same token via manual export + op vault list in interactive shell and observe success.

 

ADDITIONAL NOTES

The error message suggests a server-side authentication rejection, not a client-side configuration issue. The fact that interactive shell works but exec fails suggests the op CLI binary is checking some process context beyond environment variables. Possible security feature that's incompatible with automation use cases?

 

WORKAROUND ATTEMPTED

None successful. Manual execution required for now.

 

QUESTIONS

Does the op CLI check process lineage or TTY status when validating service account tokens? Why does the config file cache a device ID that conflicts with service account deviceUuid? Is there a way to force service account authentication without any cached state interfering?

 

1 Reply

  • thecatfix's avatar
    thecatfix
    Dedicated Contributor
    I hit a very similar “works interactive, fails in automation” wall with op in agent/exec contexts, and after a bunch of time spent fighting it we stopped trying to make service-account auth be our runtime dependency.
    Pragmatic workaround:
    1. Stop calling op at runtime for hot paths (webhooks, sync loops, retrain jobs).
    2. Inject the key once, run the operation, and then rotate/delete.
    Concretely, for automation jobs that need an API key:
    • pass the key as an env var for that single run (or a root-owned systemd drop-in if we need unattended operation),
    • run the job,
    • then rotate the key later.
    
    This avoids:
    • op signin vs eval "$(op signin)" weirdness in non-interactive shells,
    • device/UUID caching surprises (~/.config/op/config),
    • rate limits / “secure mediation layer” turning into a failure injector mid-run.
    Why I think your report is onto something:
    The error string (“Signin credentials are not compatible with the provided user auth from server”) smells like the CLI is making a determination based on more than just OP_SERVICE_ACCOUNT_TOKEN—possibly device registration state, daemon state, or non-interactive/TTY detection. Your observation that ~/.config/op/config regenerates a device id that doesn’t match the token’s embedded device UUID is exactly the kind of mismatch that would explain a server-side reject in one context but not the other.
    If you must keep using service accounts in automation, the “boring under pressure” version  is:
    • fetch secrets once (manually or via an interactive step),
    • store them in a locked-down systemd environment override (root-owned, 0600, not in repo),
    • avoid repeated op calls in tight loops (rate limit + flakiness),
    • treat op as provisioning, not runtime dependency.
    
    If 1Password wants this to be a supported pattern, IMO the CLI needs:
    a documented, supported non-interactive service-account auth mode with no TTY assumptions. 
    • deterministic device identity behavior (no surprise device UUID conflicts),
    • clear retry-after semantics when rate-limited.
    Not sure if this is the Environments feature or the Server Connect.
    Its really confusing trying to figure it out