Skip to content

Commit 89c5571

Browse files
authored
feat: add the ability to refresh tokens (#277)
1 parent 4a7d97e commit 89c5571

File tree

2 files changed

+61
-5
lines changed

2 files changed

+61
-5
lines changed

auth/device_flow.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,29 @@ func (c Config) PollToken(ctx context.Context, code *DeviceCode) (*Token, *atlas
110110
}
111111
}
112112

113-
// Revoke takes an access or refresh token and revokes it.
114-
func (c Config) Revoke(ctx context.Context, token, tokenTypeHint string) (*atlas.Response, error) {
113+
// RefreshToken takes a refresh token and gets a new access token.
114+
func (c Config) RefreshToken(ctx context.Context, token string) (*Token, *atlas.Response, error) {
115+
req, err := c.NewRequest(ctx, http.MethodPost, deviceBasePath+"/token",
116+
url.Values{
117+
"client_id": {c.ClientID},
118+
"refresh_token": {token},
119+
"scope": {strings.Join(c.Scopes, " ")},
120+
"grant_type": {"refresh_token"},
121+
},
122+
)
123+
if err != nil {
124+
return nil, nil, err
125+
}
126+
var t *Token
127+
resp, err2 := c.Do(ctx, req, &t)
128+
if err2 != nil {
129+
return nil, resp, err2
130+
}
131+
return t, resp, err2
132+
}
133+
134+
// RevokeToken takes an access or refresh token and revokes it.
135+
func (c Config) RevokeToken(ctx context.Context, token, tokenTypeHint string) (*atlas.Response, error) {
115136
req, err := c.NewRequest(ctx, http.MethodPost, deviceBasePath+"/revoke",
116137
url.Values{
117138
"client_id": {c.ClientID},

auth/device_flow_test.go

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,42 @@ func TestConfig_GetToken(t *testing.T) {
7777
}
7878
results, _, err := config.GetToken(ctx, code.DeviceCode)
7979
if err != nil {
80-
t.Fatalf("PollToken returned error: %v", err)
80+
t.Fatalf("GetToken returned error: %v", err)
81+
}
82+
83+
expected := &Token{
84+
AccessToken: "secret1",
85+
RefreshToken: "secret2",
86+
Scope: "openid",
87+
IDToken: "idtoken",
88+
TokenType: "Bearer",
89+
ExpiresIn: 3600,
90+
}
91+
92+
if diff := deep.Equal(results, expected); diff != nil {
93+
t.Error(diff)
94+
}
95+
}
96+
97+
func TestConfig_RefreshToken(t *testing.T) {
98+
config, mux, teardown := setup()
99+
defer teardown()
100+
101+
mux.HandleFunc("/api/private/unauth/account/device/token", func(w http.ResponseWriter, r *http.Request) {
102+
testMethod(t, r)
103+
fmt.Fprint(w, `{
104+
"access_token": "secret1",
105+
"refresh_token": "secret2",
106+
"scope": "openid",
107+
"id_token": "idtoken",
108+
"token_type": "Bearer",
109+
"expires_in": 3600
110+
}`)
111+
})
112+
113+
results, _, err := config.RefreshToken(ctx, "secret2")
114+
if err != nil {
115+
t.Fatalf("RefreshToken returned error: %v", err)
81116
}
82117

83118
expected := &Token{
@@ -133,15 +168,15 @@ func TestConfig_PollToken(t *testing.T) {
133168
}
134169
}
135170

136-
func TestConfig_Revoke(t *testing.T) {
171+
func TestConfig_RevokeToken(t *testing.T) {
137172
config, mux, teardown := setup()
138173
defer teardown()
139174

140175
mux.HandleFunc("/api/private/unauth/account/device/revoke", func(w http.ResponseWriter, r *http.Request) {
141176
testMethod(t, r)
142177
})
143178

144-
_, err := config.Revoke(ctx, "a", "refresh_token")
179+
_, err := config.RevokeToken(ctx, "a", "refresh_token")
145180
if err != nil {
146181
t.Fatalf("RequestCode returned error: %v", err)
147182
}

0 commit comments

Comments
 (0)