Skip to content

Commit 7b0efe7

Browse files
committed
feat: default coder.useKeyring to true and harden shared credential handling
Store session tokens in the OS keyring by default on macOS and Windows, passing --use-keyring explicitly to CLI 2.29 and later. Model the CLI store as shared (the CLI's own directory, or a user directory on 2.31+) or private (a file in the extension's per-deployment directory), and treat CODER_CONFIG_DIR like a user --global-config. Record who minted each stored token so logout runs coder logout against a shared store only for a token the extension created and the CLI still holds. Ask before adopting the CLI's session for a different user. Show an error with Open Settings when the CLI cannot store the token at login, and a Show Output button when logout cannot remove every credential. Read keyring credentials only for https URLs, since the CLI keys keyring entries by host without the scheme. Require CLI 2.32 to read tokens back, where file mode checks the stored URL against --url. Closes #1106
1 parent a91ae70 commit 7b0efe7

30 files changed

Lines changed: 1272 additions & 1289 deletions

‎CHANGELOG.md‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,34 @@
55
from published versions since it shows up in the VS Code extension changelog
66
tab and is confusing to users. Add it back between releases if needed. -->
77

8+
## Unreleased
9+
10+
### Changed
11+
12+
- Store session tokens in the OS keyring by default on macOS and Windows. The
13+
entry is shared with the `coder` CLI, so signing in here also signs in the
14+
CLI. Requires Coder CLI 2.29.0 or later; older CLIs and Linux keep using a
15+
file. To opt out, set `coder.useKeyring` to `false`.
16+
- Pass `coder.useKeyring` to the CLI as `--use-keyring`, so the setting wins
17+
over the `CODER_USE_KEYRING` environment variable.
18+
- Honor `CODER_CONFIG_DIR` like `--global-config` in `coder.globalFlags`.
19+
- Read the `coder` CLI's session only on Coder CLI 2.32.0 or later, up from
20+
2.31.0, where the CLI checks the stored URL against the one you connect to.
21+
- Ask before signing in with the `coder` CLI's session when it belongs to a
22+
different user than your previous session.
23+
- Show an error with **Open Settings** when the CLI cannot store the token at
24+
login, and a **Show Output** button when logout cannot remove every
25+
credential.
26+
27+
### Security
28+
29+
- Sign out the `coder` CLI only when it still holds the token this extension
30+
created. A session that came from the CLI is removed from the extension
31+
without signing the CLI out.
32+
- Read the CLI's keyring entry only for `https` deployments. The entry is keyed
33+
by host, so an `http` address for the same host would receive the `https`
34+
session's token.
35+
836
## [v1.16.2](https://github.com/coder/vscode-coder/releases/tag/v1.16.2) 2026-08-25
937

1038
### Fixed

‎package.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@
195195
"ignoreSync": true
196196
},
197197
"coder.globalFlags": {
198-
"markdownDescription": "Global flags to pass to every Coder CLI invocation. Enter each flag as a separate array item, in order. Do **not** include the `coder` command itself. See the [CLI reference](https://coder.com/docs/reference/cli) for available global flags.\n\nSupports `${env:VAR}`, `${userHome}`, and a leading `~`. For `--flag=value` items the expansion applies to the value half, so `--cfg=~/coder` works.\n\nSet `--global-config` here to point the CLI at a shared config directory (e.g. `--global-config=~/.config/coderv2` to share login/auth with the Coder CLI); requires a deployment on 2.31.0+ and is ignored when `#coder.useKeyring#` is active. The `--use-keyring` flag is ignored; use `#coder.useKeyring#` instead.\n\nFor `--header-command`, precedence is: `#coder.headerCommand#` setting, then `CODER_HEADER_COMMAND` environment variable, then the value specified here.",
198+
"markdownDescription": "Global flags to pass to every Coder CLI invocation. Enter each flag as a separate array item, in order. Do **not** include the `coder` command itself. See the [CLI reference](https://coder.com/docs/reference/cli) for available global flags.\n\nSupports `${env:VAR}`, `${userHome}`, and a leading `~`. For `--flag=value` items the expansion applies to the value half, so `--cfg=~/coder` works.\n\nTo share a config directory with the `coder` CLI, add `--global-config` here (for example `--global-config=~/.config/coderv2`) or set `CODER_CONFIG_DIR`. Requires Coder CLI 2.32.0 or later. A `--use-keyring` item is ignored; use `#coder.useKeyring#` instead.\n\nFor `--header-command`, precedence is: `#coder.headerCommand#` setting, then `CODER_HEADER_COMMAND` environment variable, then the value specified here.",
199199
"type": "array",
200200
"items": {
201201
"type": "string"
@@ -204,9 +204,9 @@
204204
"ignoreSync": true
205205
},
206206
"coder.useKeyring": {
207-
"markdownDescription": "Store session tokens in the OS keyring (macOS Keychain, Windows Credential Manager) instead of plaintext files. Requires CLI >= 2.29.0 (>= 2.31.0 to sync login from CLI to VS Code). This will attempt to sync between the CLI and VS Code since they share the same keyring entry. It will log you out of the CLI if you log out of the IDE, and vice versa. Has no effect on Linux.",
207+
"markdownDescription": "Store session tokens in the OS keyring (macOS Keychain, Windows Credential Manager) instead of a file. Requires Coder CLI 2.29.0 or later; 2.32.0 or later to sign in with the CLI's existing session. Has no effect on Linux.\n\nThe keyring entry is shared with the `coder` CLI: signing in here also signs in the CLI, and signing out signs out the CLI only when it still holds the token this extension created.",
208208
"type": "boolean",
209-
"default": false,
209+
"default": true,
210210
"scope": "application"
211211
},
212212
"coder.networkThreshold.latencyMs": {

‎src/commands.ts‎

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -708,12 +708,25 @@ export class Commands {
708708
await this.deploymentManager.clearDeployment("logout");
709709

710710
if (deployment) {
711-
const cleared = await this.cliManager.clearCredentials(deployment.url);
711+
const session = await this.secretsManager.getSessionAuth(
712+
deployment.safeHostname,
713+
);
714+
const cleared = await this.cliManager.clearCredentials(
715+
deployment.url,
716+
session,
717+
);
712718
await this.secretsManager.clearAllAuthData(deployment.safeHostname);
713719
if (!cleared) {
714-
vscode.window.showWarningMessage(
715-
'You\'ve been logged out of Coder, but some credentials could not be removed. Log out again to retry, or run "coder logout" in a terminal.',
716-
);
720+
vscode.window
721+
.showWarningMessage(
722+
'You\'ve been logged out of Coder, but some credentials could not be removed. Log out again to retry, or run "coder logout" in a terminal.',
723+
"Show Output",
724+
)
725+
.then((action) => {
726+
if (action === "Show Output") {
727+
this.logger.show();
728+
}
729+
});
717730
return { success: false, reason: "cleanup_incomplete" };
718731
}
719732
}
@@ -790,7 +803,7 @@ export class Commands {
790803
const selectedHostname = selected.hostnames[0];
791804
const auth = await this.secretsManager.getSessionAuth(selectedHostname);
792805
if (auth?.url) {
793-
await this.cliManager.clearCredentials(auth.url);
806+
await this.cliManager.clearCredentials(auth.url, auth);
794807
}
795808
await this.secretsManager.clearAllAuthData(selectedHostname);
796809
this.logger.info("Removed credentials for", selectedHostname);
@@ -812,7 +825,7 @@ export class Commands {
812825
selected.hostnames.map(async (h) => {
813826
const auth = await this.secretsManager.getSessionAuth(h);
814827
if (auth?.url) {
815-
await this.cliManager.clearCredentials(auth.url);
828+
await this.cliManager.clearCredentials(auth.url, auth);
816829
}
817830
await this.secretsManager.clearAllAuthData(h);
818831
}),

0 commit comments

Comments
 (0)