Skip to content

[profile] Enable token cache encryption on MacOS and Linux - #33849

Draft
Yeming Liu (isra-fel) wants to merge 15 commits into
devfrom
shared/token-cache-encryption
Draft

[profile] Enable token cache encryption on MacOS and Linux#33849
Yeming Liu (isra-fel) wants to merge 15 commits into
devfrom
shared/token-cache-encryption

Conversation

@isra-fel

@isra-fel Yeming Liu (isra-fel) commented Aug 5, 2026

Copy link
Copy Markdown
Member

🤖 PR Validation — ️✔️ All clear

Breaking Changes Tests
️✔️ None ️✔️ 130/130

Related command
az login, az logout, az account clear

Description

Token cache encryption has been Windows-only so far. On macOS and Linux the MSAL token cache and the service principal secret store are written to disk in plaintext, so anything that can read ~/.azure can read a usable credential.

This PR turns encryption on by default on all platforms, and fixes what that exposes in the surrounding code.

  • Encryption on by default. should_encrypt_token_cache now falls back to True instead of sys.platform.startswith('win32'). core.encrypt_token_cache=false still opts out, and is now the documented escape hatch for machines where the keyring prompt is unwanted.

  • Real names in the OS credential store. Keychain and libsecret entries were registered under placeholders (my_service_name, my_account_name, my_schema_name, my_attr1=foo). They now use Microsoft Azure CLI plus the persistence type, so a user browsing Keychain Access or Seahorse sees Microsoft Azure CLI - Token cache / - Secret store rather than an unlabeled row.

  • Separate file extension for the signal file. With encryption on, the payload lives in the OS credential store and the file on disk is only a last-modified signal — it is not .bin content. Signal files now use .sig so the three states (.bin encrypted-on-Windows, .json plaintext, .sig signal) are distinguishable, which is what makes correct cleanup possible.

  • Logout actually clears the credential. az logout / az account clear used to just delete the cache files. With encryption on, that orphans the payload in libsecret/Keychain: the credential stays readable. erase_persistence now overwrites the payload with an empty one under the same CrossPlatLock used by writers, then removes the files. It also cleans up files from every extension, so switching encrypt_token_cache doesn't leave stale credentials behind.

  • Plaintext fallback is graceful, and reported. LibsecretPersistence fails to initialize in some Linux environments (no D-Bus session, headless containers). Instead of failing the command, we fall back to FilePersistence and warn once at sign-in that credentials are in plaintext. The warning is suppressed in Cloud Shell, where nothing can be installed to fix it.

  • Honest warnings when a clear can't reach the credential store. With encryption off we deliberately do not touch the keyring — emptying it would raise the unlock prompt the user opted out of. The .sig file is kept as evidence that a payload may still be there, and the user is told how to remove it. If the clear itself fails (typically another az process holding the lock), nothing is removed and the user is asked to retry, rather than the files being deleted while the credential survives.

Testing Guide

macOS / Linux, with a keyring available:

az login
ls ~/.azure/msal_token_cache.*        # msal_token_cache.sig, no .json
# macOS: Keychain Access shows "Microsoft Azure CLI - Token cache"
# Linux: secret-tool / Seahorse shows "Microsoft Azure CLI - Token cache"

az account clear
az account get-access-token           # must fail: credential is gone, not just the file

Opting out:

az config set core.encrypt_token_cache=false
az login
ls ~/.azure/msal_token_cache.*        # msal_token_cache.json
az account clear                      # no keyring prompt; warns that the store may still hold credentials

Linux without a keyring (e.g. docker run with no D-Bus): az login succeeds and warns that credentials are stored in plaintext.

Unit tests:

azdev test --src-file-changed
python -m pytest src/azure-cli-core/azure/cli/core/auth/tests/test_persistence.py

History Notes

[Core] az login: Enable token cache and service principal secret encryption by default on macOS and Linux. Set core.encrypt_token_cache=false to opt out.
[Core] az account clear: Also remove leftover plaintext cache files when core.encrypt_token_cache is on.
[Core] az logout: Clear the persisted credential according to core.encrypt_token_cache — the OS credential store payload when encryption is on, the plaintext files when it is off.


This checklist is used to make sure that common guidelines for a pull request are followed.

@yonzhan

Copy link
Copy Markdown
Collaborator

Thank you for your contribution! We will review the pull request and get back to you soon.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@yonzhan

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).

@x-engineering-agent

Copy link
Copy Markdown
Contributor

Live test skipped

⏭️ Skipping the live test for this revision because no new test file was added (tests/**/test_*.py).

The live-test pipeline runs only the test files a PR changes, so there is nothing to execute for this commit. This is informational — a regression test is encouraged where it makes sense, but not required. If a test file is added in a later commit, the live test will run automatically.

@x-engineering-agent x-engineering-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Review Summary

This PR currently has failing checks and needs attention from the author before it can be merged.

  • Live test (Tester): passed
  • CI checks: 89/95 passed, 4 failed, 0 pending

Failed checks:

Please review the linked job logs and update the PR to resolve the style/build failures.

@xuming-ms
xuming-ms force-pushed the shared/token-cache-encryption branch from 65ed354 to ac81221 Compare August 30, 2026 23:56
@xuming-ms xuming-ms self-assigned this Sep 1, 2026
@a0x1ab Aditya Pujara (a0x1ab) added X Engineering Agent Reviewed Pull request reviewed by X Engineering Agent and removed azure-client-tools-agent labels Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

X Engineering Agent Reviewed Pull request reviewed by X Engineering Agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants