Skip to content
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

Provide a way for a client to access refreshed Access Token #131

Closed
x1ddos opened this issue Jul 5, 2015 · 10 comments
Closed

Provide a way for a client to access refreshed Access Token #131

x1ddos opened this issue Jul 5, 2015 · 10 comments

Comments

@x1ddos
Copy link

x1ddos commented Jul 5, 2015

It is often desirable for a program to get access to newly obtained access token upon refresh. Consider the following use case:

  • A cmd line program authenticates a user, stores access token and uses it on every invocation.
  • After a while, the access token is expired.
  • Every subsequent invocation of such program will result in potentially unnecessary token refresh as the program has no way of updating the access token it stored in the first step.

I'm proposing the following:

// ChanneledTokenSource creates a TokenSource that returns t until it expires,
// automatically refreshing as necessary using the provided context.
// Refreshed Token will also be sent on the returned channel.
func (c *Config) ChannelledTokenSource(ctx context.Context, t *Token) (TokenSource, <-chan *Token)

Then, a program could do something like this:

src, rc := c.ChannelledTokenSource(ctx, t)

go func() {
  for {
    newt := <-rc
    updateAccessToken(newt)
  }
}()

cl := oauth2.NewClient(ctx, src)

I can open a CL if you guys think this is useful.

@johnl
Copy link

johnl commented Aug 2, 2015

For reference, there used to be support for token caches but it was removed for some reason. See 93ad3f4

@x1ddos
Copy link
Author

x1ddos commented Oct 27, 2015

@bradfitz
Copy link
Contributor

Okay, I read this now. Let's just use a func. Then the caller can do a channel or goroutine if they want.

Maybe we create a new TokenSource which calls your func when the Token is refreshed.

// NotifyUseSource returns a TokenSource which calls notify whenever src is used.
// The arguments to notify are the return values from src.Token.
// The returned TokenSource returns the Token from src and the returned error from notify.
// The notify func is allowed to change or add an an error from src, but cannot change
// a non-nil error to nil, as there would be no Token to return.
// A NotifyUseSource can be used to refresh cached tokens.
func NotifyUseSource(src TokenSource, notify func(*Token, error) error) TokenSource

/cc @adg @rakyll

@x1ddos
Copy link
Author

x1ddos commented Oct 27, 2015

Sounds good to use a func but it would be redundant to call it every time a token is used. It suffices to call notify only when the token is refreshed.

@bradfitz
Copy link
Contributor

Yes, you would compose it with a ReuseTokenSource to get that effect.

@x1ddos
Copy link
Author

x1ddos commented Oct 27, 2015

Right. It's just Config.TokenSource already returns a reuseTokenSource. So, if you start with a Config:

c := &Config{...}
// src is reuseTokenSource(tokenRefresher)
src := c.TokenSource(ctx, tok)
// src is reuseTokenSource(notifyUseToken(reuseTokenSource(tokenRefresher)))
src = ReuseTokenSource(nil, NotifyUseSource(src, notifyMe))

Unless, Config could as well provide:

func (c *Config) NotifyUseTokenSource(ctx context.Context, t *Token, notify func(*Token, error) error) TokenSource

@bradfitz
Copy link
Contributor

I'd prefer the composable way, rather than the all-in-one, one-special-case way.

@x1ddos
Copy link
Author

x1ddos commented Oct 27, 2015

Alright. I'll work on a CL.

@x1ddos
Copy link
Author

x1ddos commented Oct 27, 2015

@x1ddos
Copy link
Author

x1ddos commented Oct 28, 2015

Closing as duplicate of #84

@x1ddos x1ddos closed this as completed Oct 28, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants