Skip to content

Commit 3490c99

Browse files
committed
Adds TokenSourceWithOptions to refresh token that allows for setting additional attributes
- Support for rfc 7523 in refresh token
1 parent 32d34ef commit 3490c99

File tree

2 files changed

+46
-6
lines changed

2 files changed

+46
-6
lines changed

oauth2.go

+20-6
Original file line numberDiff line numberDiff line change
@@ -242,14 +242,14 @@ func (c *Config) Client(ctx context.Context, t *Token) *http.Client {
242242
return NewClient(ctx, c.TokenSource(ctx, t))
243243
}
244244

245-
// TokenSource returns a [TokenSource] that returns t until t expires,
246-
// automatically refreshing it as necessary using the provided context.
245+
// TokenSourceWithOptions returns a [TokenSource] that returns t until t expires,
247246
//
248-
// Most users will use [Config.Client] instead.
249-
func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource {
247+
// This method provides a way to pass options to the token source.
248+
func (c *Config) TokenSourceWithOptions(ctx context.Context, t *Token, opts ...AuthCodeOption) TokenSource {
250249
tkr := &tokenRefresher{
251250
ctx: ctx,
252251
conf: c,
252+
opts: opts,
253253
}
254254
if t != nil {
255255
tkr.refreshToken = t.RefreshToken
@@ -260,12 +260,21 @@ func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource {
260260
}
261261
}
262262

263+
// TokenSource returns a [TokenSource] that returns t until t expires,
264+
// automatically refreshing it as necessary using the provided context.
265+
//
266+
// Most users will use [Config.Client] instead.
267+
func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource {
268+
return c.TokenSourceWithOptions(ctx, t)
269+
}
270+
263271
// tokenRefresher is a TokenSource that makes "grant_type=refresh_token"
264272
// HTTP requests to renew a token using a RefreshToken.
265273
type tokenRefresher struct {
266274
ctx context.Context // used to get HTTP requests
267275
conf *Config
268276
refreshToken string
277+
opts []AuthCodeOption
269278
}
270279

271280
// WARNING: Token is not safe for concurrent access, as it
@@ -277,10 +286,15 @@ func (tf *tokenRefresher) Token() (*Token, error) {
277286
return nil, errors.New("oauth2: token expired and refresh token is not set")
278287
}
279288

280-
tk, err := retrieveToken(tf.ctx, tf.conf, url.Values{
289+
v := url.Values{
281290
"grant_type": {"refresh_token"},
282291
"refresh_token": {tf.refreshToken},
283-
})
292+
}
293+
for _, opt := range tf.opts {
294+
opt.setValue(v)
295+
}
296+
297+
tk, err := retrieveToken(tf.ctx, tf.conf, v)
284298

285299
if err != nil {
286300
return nil, err

oauth2_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,32 @@ func TestRefreshToken_RefreshTokenReplacement(t *testing.T) {
551551
}
552552
}
553553

554+
func TestRefreshToken_RefreshWithOpts(t *testing.T) {
555+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
556+
body, err := io.ReadAll(r.Body)
557+
if err != nil {
558+
t.Errorf("Failed reading request body: %s.", err)
559+
}
560+
if string(body) != "foo=bar&grant_type=refresh_token&refresh_token=OLD_REFRESH_TOKEN" {
561+
t.Errorf("Unexpected exchange payload; got %q", body)
562+
}
563+
w.Header().Set("Content-Type", "application/json")
564+
w.Write([]byte(`{"access_token":"ACCESS_TOKEN", "scope": "user", "token_type": "bearer", "refresh_token": "NEW_REFRESH_TOKEN"}`))
565+
return
566+
}))
567+
defer ts.Close()
568+
conf := newConf(ts.URL)
569+
tkr := conf.TokenSourceWithOptions(context.Background(), &Token{RefreshToken: "OLD_REFRESH_TOKEN"}, SetAuthURLParam("foo", "bar"))
570+
tk, err := tkr.Token()
571+
if err != nil {
572+
t.Errorf("got err = %v; want none", err)
573+
return
574+
}
575+
if want := "NEW_REFRESH_TOKEN"; tk.RefreshToken != want {
576+
t.Errorf("RefreshToken = %q; want %q", tk.RefreshToken, want)
577+
}
578+
}
579+
554580
func TestRefreshToken_RefreshTokenPreservation(t *testing.T) {
555581
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
556582
w.Header().Set("Content-Type", "application/json")

0 commit comments

Comments
 (0)