Token Caching
Tokens are stored in the operating system keyring, not in config.toml.
| Platform | Store |
|---|---|
| macOS | Keychain |
| Windows | Credential Manager |
| Linux | Secret Service-compatible keyring |
On Windows the token is split across several Credential Manager entries. Credential Manager caps a
single credential at 2560 bytes and a Microsoft Graph token bundle is routinely larger — the access
token alone can exceed it — so the CLI writes a <profile>:token header holding the chunk count and
<profile>:token:0, <profile>:token:1 and so on holding the bytes. Seeing several entries per
profile is expected; teams auth logout removes all of them. macOS and Linux keep a single item per
profile.
Token size is a property of the tenant's consent grant rather than of the scopes the CLI asks for, so requesting fewer scopes does not reliably shrink it.
File token store
Some processes cannot use the keyring. A daemon on macOS cannot answer the Keychain prompt, and macOS
asks again for every new or upgraded binary, so an unattended process waits on a dialog nobody sees.
A Linux server or container often has no Secret Service at all. For these, set
TEAMS_CLI_TOKEN_STORE=file and sign in once with it set:
export TEAMS_CLI_TOKEN_STORE=file
teams auth login --device-code
Tokens then live in files under the config directory's tokens/: one file per profile
(<profile>.token), plus profile-index. On Unix the directory is 0700 and each file 0600. Each
write goes to a temporary file that is flushed to disk and renamed into place, so a reader never
sees a partial token.
- The files hold the refresh token unencrypted, protected only by file permissions. Prefer the keyring wherever a process can use it; on Windows the file store relies on the profile directory's ACL. A token file readable by other users draws a warning on stderr.
- The two stores do not share sessions. After switching, run
teams auth loginagain. keyring(the default, also accepted askeychain) andfileare the only values. Anything else is refused before the command runs, withINVALID_INPUTand exit code 2.- Keep the
tokens/directory out of backups, images and support bundles.
Access tokens are refreshed automatically when the stored token is expired or close to expiry and a refresh token is available.
Use auth refresh when you need to pick up newly consented scopes without a browser prompt:
teams auth refresh
teams auth refresh --scopes "User.Read People.Read Files.Read.All offline_access"
Scope selection for an explicit refresh is intentionally non-destructive:
--scopesorTEAMS_CLI_SCOPESwins when supplied.- Otherwise, a
scopesvalue on the selected profile is requested. - If neither is configured,
auth refreshreuses the stored token's granted scopes instead of falling back to the built-in defaults and potentially narrowing the session.
The CLI adds offline_access to delegated scope overrides automatically.
If refresh fails because the token is too old, revoked, or was created without offline_access, sign in again with teams auth login --device-code.
Use teams auth logout or teams auth logout --all to remove stored credentials.
TEAMS_CLI_ACCESS_TOKEN bypasses the keyring for one process and cannot be refreshed by the CLI. It must contain a Microsoft Graph access token. Captured Teams client tokens, including fossteams/teams-token JWT files, are not compatible with Graph commands.