- Notifications
You must be signed in to change notification settings - Fork1.1k
chore: refactor codersdk to use SessionTokenProvider#19565
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
spikecurtis commentedAug 27, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
This stack of pull requests is managed byGraphite. Learn more aboutstacking. |
7789799 tod9ee61fCompare
mafredri 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.
LGTM in general, just a few API design related suggestions.
| tokenHeader=c.client.SessionTokenHeader | ||
| wsOptions:=&websocket.DialOptions{ | ||
| HTTPClient:c.client.HTTPClient, | ||
| // Need to disable compression to avoid a data-race. |
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.
Is this something we could fix inwebsocket?
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 actually don't know. That's just copied from the existing code; I wanted to limit my changes to just session token stuff.
| // SetSessionTokenreturns the currently set token for the client. | ||
| // SetSessionTokensets a fixed token for the client. | ||
| func (c*Client)SetSessionToken(tokenstring) { | ||
| c.SetSessionTokenProvider(FixedSessionTokenProvider{SessionToken:token}) |
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 can see the logic here, but I think it would make more sense to call provider.SetSessionToken() and implement the method on FixedSessionTokenProvider. Other providers may choose to ignore it or do something else. If this, for example, was a file provider underneath, one may wish to write the token rather than have it be ephemeral.
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 actually want to go the other direction and drop this method entirely. The abstraction here is a session tokenprovider, not a session tokenstore.
I kept the method around to keep this PR relatively minimal in size, but we are almost always* using this method to set a fixed session token at start of day. There just aren't really many circumstances where you find out the session token later.
- 2 exceptions I can think of:
coder loginwhere we get the token pasted in, and then check it. But even in that case, you can create the Client after the token is pasted in. It's not really safe (and has not been) to useSetSessionToken()after the client has been referenced by other goroutines, so it's better to create a new Client.Token exchange based on VM identity credentials --- that is the subject of the PR stacked on top of this one. This is based on anonymous
ExchangeTokenfunction callbacks that callSetSessionToken()before the PR above this one, but that's pretty fragile and not threadsafe.
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.
Alright, that makes sense to me and I'm fine with the approach. I'd like it if we could mark this method deprecated, however, and mention that it replaces the provider.
(IIRC the Go standard deprecation comment is, on a new line:// Deprecated: Use ... instead.
codersdk/client.go Outdated
| returnc.RequestNoSessionToken(ctx,method,path,body,opts...) | ||
| } | ||
| func (c*Client)RequestNoSessionToken(ctx context.Context,method,pathstring,bodyinterface{},opts...RequestOption) (*http.Response,error) { |
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.
Question: What's the use-case for this method?
Suggestion: Can we make it a private method? At least a comment would be good, and I'd suggest renamingNo ->NoSet/Without.
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 happy to change the name.
The use-case for this method is in the PR stacked on top of this one.
Exchanging a VM identity document for a session token involves a call to Coderd. We need this option to call coderd without a session token to ensure we don't create a re-entrant loop in the token exchange code.
| // SetDialOption sets the session token on a websocket request via DialOptions | ||
| SetDialOption(options*websocket.DialOptions) | ||
| // GetSessionToken returns the session token as a string. | ||
| GetSessionToken()string |
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.
If we implementSet like proposed earlier, we can make theSessionToken field private and avoidGet here.
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.
There are still some random bits of code that do oddball stuff like putting the session token in a Cookie jar, rather than using the custom header. Until that stuff is cleaned up we still need an escape hatch to just get the session token from the Client.
mafredri 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.
No other remaining requests than updating theSetSessionToken comment and marking it deprecated, approved 👍🏻.
53e1b76 to7ea81d2Compare192c81e intomainUh oh!
There was an error while loading.Please reload this page.

Uh oh!
There was an error while loading.Please reload this page.
Refactors
codersdk.Client's use of session tokens to use aSessionTokenProvider, which abstracts the obtaining and storing of the session token.The main motiviation is to unify Agent authentication an an upstack PR, which can use cloud instance identity via token exchange, rather than a fixed session token.
However, the abstraction could also allow functionality like obtaining the session token from other external sources like the OS credential manager, or an external secret/key management system like Vault.