-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
x/oauth2: add Token.ExpiresIn struct field #61417
Comments
This proposal has been added to the active column of the proposals project |
Is the specific proposal here to change Token.UnmarshalJSON to set the Expiry field based on expires_in? |
Yes. |
I'm very confused, since Token.UnmarshalJSON does not exist and yet the top proposal above mentions it. What is the specific API change we are discussing? Or do you have a link to an implementation of the change? |
I'm sorry for the confusion. The request here is to allow unmarshaling an |
What is the specific API that we should add? |
@rsc I'm proposing to add the ability of unmarshaling tokens from JSON. I'm in no position to propose a specific api. As written before options I see are:
I feel the weekly round trips on this proposal do not really help to move it forward as apparently I cannot make the required contribution. Is there any chance one of the oauth2 owners joins here to improve the contribution? |
@andig, I apologize for the unclear questions. When I ask what is the specific API, I mean what is the full godoc output for the API being added? For a function, what is the signature and the doc comment? For a struct field in an existing type, what is the name, type, and doc comment? And so on. It sounds like Token.UnmarshalJSON is a method, so the question is how this gets filled out:
and similarly for oauth2.TokenFromJSON. |
@rsc I'm still slightly puzzled why we are discussing the signature instead of the best approach, but let me try! Signature should be normal
Let's discuss |
Thanks for the clarification. It sounds like perhaps instead we should add an ExpiresIn int64 field to the Token so that people who want to unmarshal can do that. This would require them to consult ExpiresIn or to switch to Expiry by calling time.Now.Add themselves. It seems like a mistake to call time.Now during json.Unmarshal, since that will make json.Unmarshal produce non-repeatable results. So what do people think of adding
If we add this, then json.Unmarshal will preserve the information, and applications can use it themselves. |
The current I like the idea- sweet and simple- but I'm wondering how many bugs the will create when one uses such an unmarshaled token and it is immediately expired due to I'd further suggest to add:
|
expires_in is the field that gets sent on the wire, so it seems wrong to omit it from JSON export. Assuming we add ExpiresIn to resolve this proposal, have all remaining concerns been addressed? |
Thank you, yes 👍🏻 |
Based on the discussion above, this proposal seems like a likely accept. |
I have added https://go-review.googlesource.com/c/oauth2/+/534835 |
oauth2.DeviceAuthResponse has the convenient property that its JSON encoding is consistent with OAuth RFC 8628 Device Authorization Response https://datatracker.ietf.org/doc/html/rfc8628#section-3.2 // DeviceAuthResponse describes a successful RFC 8628 Device Authorization Response
type DeviceAuthResponse struct {
// Expiry is when the device code and user code expire. When encoding or
// decoding JSON, the following relation is used: Expiry = time.Now() + expires_in
Expiry time.Time `json:"expires_in,omitempty"` It would be neat if oauth2.Token and OAuth access token response JSON were consistent in the same way https://datatracker.ietf.org/doc/html/rfc6749#section-4.2.2 |
See @rsc's comment above:
I agree that consistency in the codebase is a high value which might make it desirable to use the same approach for both tokens (and actually was what triggered me to ask #63543 before I discovered the Unmarshal implementation). |
So concretely? type Token struct {
- Expiry time.Time `json:"expiry,omitempty"`
+ Expiry time.Time
+ ExpiresIn int64 `json:"expires_in,omitempty"`
...
}
type DeviceAuthResponse struct {
- Expiry time.Time `json:"expires_in,omitempty"`
+ Expiry time.Time
+ ExpiresIn int64 `json:"expires_in,omitempty"`
...
} Then the JSON simply agrees with OAuth RFCs without custom MarshalJSON or UnmarshalJSON. That's appealing. Functions Config.Exchange(...) and Config.DeviceAuth(...) must continue to populate Expiry based on time.Now + ExpiresIn. |
Is there a way to change that without breaking backward compatibility? |
Adding |
Based on the discussion above, this proposal seems like a likely accept. The proposal is to add one field to the Token type:
This field is automatically handled by json.Marshal and json.Unmarshal; there are no custom marshalers or unmarshalers. Code can do what it needs to with the field. |
No change in consensus, so accepted. 🎉 The proposal is to add one field to the Token type:
This field is automatically handled by json.Marshal and json.Unmarshal; there are no custom marshalers or unmarshalers. Code can do what it needs to with the field. |
Note sure how to link here in https://go-review.googlesource.com/c/oauth2/+/605955. Now points to https://github.com/golang/oauth2/issues/61417. |
@andig You can use a cross-repo issue reference, like so: |
Change https://go.dev/cl/605955 mentions this issue: |
Sorry, I don't get it right:
still points to oauth2. |
Odd. That's the right syntax; i'm not sure why gerrit's autolinker isn't parsing it correctly. Maybe something misconfigured? Here's another x/oauth2 CL showing the same problem (https://golang.org/cl/450155), whereas a recent x/tools CL shows a correct link (https://golang.org/cl/605015). In any case, it should work correctly when the commit is eventually merged. |
Thank you all for this proposal! Even in its minimal form, it's already saving me some amount of copy pasting: https://review.gerrithub.io/c/cue-lang/cue/+/1201519 |
…ExpiresIn In typical usage, Token.Expiry alone is sufficient. However, the ExpiresIn field was introduced in golang/go#61417. Even when a server returns an expires_in value in methods like Config.Exchange, only the Expiry field is updated, leaving ExpiresIn unchanged, which can cause confusion. This change ensures that the ExpiresIn field is properly updated when the server provides an expires_in value.
Change https://go.dev/cl/621215 mentions this issue: |
…ExpiresIn In typical usage, Token.Expiry alone is sufficient. However, the ExpiresIn field was introduced in golang/go#61417. Even when a server returns an expires_in value in methods like Config.Exchange, only the Expiry field is updated, leaving ExpiresIn unchanged, which can cause confusion. This change ensures that the ExpiresIn field is properly updated when the server provides an expires_in value. merges golang#748 (golang#748)
…e package Related golang/go#61417 merges golang#747 (golang#747)
Migrated from golang/oauth2#484, refs #56402 (comment)
There are a number of OAuth2 token uses outside of the oauth2 library with the token structure being the common denominator. Unfortunately, unmarshaling JSON into an
oauth2.Token
does not populate it'sExpiry
field. Hence, the token structure needs be duplicated/embedded to provide this logic as it currently lives inoauth2/internal
.Proposed solution:
Allow unmarshaling an oauth2.Token from its usual json representation, i.e. containing the
expires_in
field.An implementation choice might be to add a
Token.UnmarshalJSON
method though that might imply that (later) addingToken.MarshalJSON
may not make sense given the nature ofexpires_in
being relative to the current moment.Consequence of not implementing:
Duplicated code like https://cs.github.com/?scopeName=All+repos&scope=&q=language%3Agolang+ExpiresIn+int#.
Alternatives:
internal/RetrieveToken
to avoid new methods onToken
like Make RetrieveToken usable by client packages oauth2#354oauth2.Config
like custom exchange request attribute/header oauth2#533, Config: Refresh Token Request with Custom Parameters oauth2#521 or Add additional headers during token refresh oauth2#483The text was updated successfully, but these errors were encountered: