-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat(cli): optionally store session token in OS keyring #20256
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
9e95011 to
e401787
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very cool addition.
Thought I would come by with a perspective of how this might affect the VS Code and JetBrains plugins (and left some other comments while I was here).
In VS Code, we manually write the session file, and expect the CLI to use it. @EhabY to double check me on this.
In JetBrains, we call the login command to create the session file, but I think we also sometimes try to read the session file directly or check that it exists. @fioan89 to double check me on this.
All this to say, should using the keyring be opt-in? We may break the plugins otherwise. The main scenario that comes to my mind is that there is an expired token in the keyring and the VS Code plugin is unable to log in.
e401787 to
cffe005
Compare
Yes, as part of the OAuth work, I'm thinking of ditching that approach since it's not really secure (writing the token in plaintext to some globally accessible file). The idea I have in mind is to use VS Code's secrets API to store the |
cffe005 to
1e0ca87
Compare
Thanks for the input @code-asher! Your comments were helpful. After learning about how session tokens are used with Coder Desktop and VS Code/Jetbrains plugins I took this feature a different direction. Essentially keyring use is now opt-in, and there's a future path forward to share the session token across applications. I put more details in the notion link in the PR description. |
code-asher
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, I like how the flag also removes the ambiguity of whether the keyring will be used, very nice 👌
This change implements optional secure storage of the CLI token using the operating system keyring for Windows, with groundwork laid for macOS in a future change. Previously, the Coder CLI stored authentication tokens in plaintext configuration files, which posed a security risk because users' tokens are stored unencrypted and can be easily accessed by other processes or users with file system access. The secure storage is platform dependent. Windows Credential Manager API is used on Windows. The session token continues to be stored in plain text on macOS and Linux. macOS is omitted for now while we figure out the best path forward for compatibility with apps like Coder Desktop.
1e0ca87 to
da8034f
Compare
|
Hey everyone, sorry for the late feedback.
Coder Toolbox does only login, it no longer stores the token in plain text.
This means apps vs code coder extension and Code toolbox will have to make a deliberate choice whether or not they should use the secure keychain. Will there be a way for these two apps to query the cli and check if keyring is available 🤔 ? |
deansheather
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused what the flow is like with the support for multiple logins on separate hosts. How does the agent know which host it's supposed to use?
Windows implementation seems sound though!
|
|
||
| // keyringProvider represents an operating system keyring. The expectation | ||
| // is these methods operate on the user/login keyring. | ||
| type keyringProvider interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the provider interface need to have the service exposed as a parameter on methods? I imagine it could just be passed to the provider when it's instantiated and then used for all Set/Get/Delete operations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thinking here is I think we're better off storing the service name one level up (where we call out to a keyringProvider), rather than prescribing each keyringProvider to implement a way to store the service name. This closely mirrors what most of the OS keyring API's look like.
There's no support for logins on separate hosts right now, but the JSON storage format in the keyring should allow that in the future. I think this is consistent with how the CLI works today (it stores one token in |
code-asher
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
One minor observation from using it: it would be nice if we errored earlier when there is no keyring with coder --use-keyring login, currently it lets me go as far as pasting a token, and then it finally fails.
| const ( | ||
| // defaultServiceName is the service name used in the Windows Credential Manager | ||
| // for storing Coder CLI session tokens. | ||
| defaultServiceName = "coder-v2-credentials" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be set in sessionstore.go I wonder? Since probably we will want to share the default name with all the keyring provider implementations. Or would each implementation have a different default name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. I'm planning to cross this bridge when I add the macOS support shortly. If they can be the same, I'll move this to sessionstore.go at that time.
Good observation! I made a small change to fail fast in this scenario, and updated the corresponding test. |
This change implements optional secure storage of the CLI token using the operating system keyring for Windows, with groundwork laid for macOS in a future change. Previously, the Coder CLI stored authentication tokens in plaintext configuration files, which posed a security risk because users' tokens are stored unencrypted and can be easily accessed by other processes or users with file system access.
The keyring is opt-in to preserve compatibility with applications (like the JetBrains Toolbox plugin, VS code plugin, etc). Users can opt into keyring use with a new
--use-keyringflag.The secure storage is platform dependent. Windows Credential Manager API is used on Windows. The session token continues to be stored in plain text on macOS and Linux. macOS is omitted for now while we figure out the best path forward for compatibility with apps like Coder Desktop.
https://www.notion.so/coderhq/CLI-Session-Token-in-OS-Keyring-293d579be592808b8b7fd235304e50d5
#19403