@@ -197,7 +197,7 @@ func TestPersistingTokenSource_PersistsRotatedRefreshToken(t *testing.T) {
197197
198198 store := & stubStore {tok : stored }
199199 base := oauth2 .StaticTokenSource (& oauth2.Token {AccessToken : "access" , RefreshToken : "new-refresh-token" })
200- ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored )
200+ ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored , "" )
201201
202202 if _ , err := ts .Token (); err != nil {
203203 t .Fatalf ("Token: %v" , err )
@@ -246,7 +246,7 @@ func TestPersistingTokenSource_PersistsAccessToken(t *testing.T) {
246246 RefreshToken : "refresh-token" ,
247247 Expiry : expires ,
248248 })
249- ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored )
249+ ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored , "" )
250250
251251 if _ , err := ts .Token (); err != nil {
252252 t .Fatalf ("Token: %v" , err )
@@ -279,7 +279,118 @@ func TestPersistingTokenSource_NoRotationDoesNotPersist(t *testing.T) {
279279 }
280280 store := & stubStore {tok : stored }
281281 base := oauth2 .StaticTokenSource (& oauth2.Token {AccessToken : "access" , RefreshToken : "same-token" , Expiry : expires })
282- ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored )
282+ ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored ,
"" )
283+
284+ if _ , err := ts .Token (); err != nil {
285+ t .Fatalf ("Token: %v" , err )
286+ }
287+
288+ if store .setCalls != 0 {
289+ t .Fatalf ("expected no SetToken calls, got %d" , store .setCalls )
290+ }
291+ }
292+
293+ func TestPersistingTokenSource_PersistsObservedGrantedScopeUpgrade (t * testing.T ) {
294+ gmailScopes , err := googleauth .Scopes (googleauth .ServiceGmail )
295+ if err != nil {
296+ t .Fatalf ("gmail scopes: %v" , err )
297+ }
298+ grantedScopes := normalizeScopeList (append ([]string {
299+ "https://www.googleapis.com/auth/calendar" ,
300+ "openid" ,
301+ }, gmailScopes ... ))
302+ stored := secrets.Token {
303+ 304+ RefreshToken : "same-token" ,
305+ Services : []string {"calendar" },
306+ Scopes : []string {
307+ "https://www.googleapis.com/auth/calendar" ,
308+ "openid" ,
309+ },
310+ }
311+ store := & stubStore {tok : stored }
312+ base := oauth2 .StaticTokenSource ((& oauth2.Token {
313+ AccessToken : "access" ,
314+ RefreshToken : "same-token" ,
315+ }).WithExtra (map [string ]any {
316+ "scope" : strings .Join (grantedScopes , " " ),
317+ }))
318+ ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored ,
"gmail" )
319+
320+ if _ , err := ts .Token (); err != nil {
321+ t .Fatalf ("Token: %v" , err )
322+ }
323+
324+ if store .setCalls != 1 {
325+ t .Fatalf ("expected 1 SetToken call, got %d" , store .setCalls )
326+ }
327+
328+ wantServices := []string {"calendar" , "gmail" }
329+ if ! reflect .DeepEqual (store .lastSet .Services , wantServices ) {
330+ t .Fatalf ("services=%#v want %#v" , store .lastSet .Services , wantServices )
331+ }
332+
333+ wantScopes := grantedScopes
334+ if ! reflect .DeepEqual (store .lastSet .Scopes , wantScopes ) {
335+ t .Fatalf ("scopes=%#v want %#v" , store .lastSet .Scopes , wantScopes )
336+ }
337+ }
338+
339+ func TestPersistingTokenSource_DoesNotAddServiceForPartialObservedGrant (t * testing.T ) {
340+ stored := secrets.Token {
341+ 342+ RefreshToken : "same-token" ,
343+ AccessToken : "access" ,
344+ Services : []string {"calendar" },
345+ Scopes : []string {"https://www.googleapis.com/auth/calendar" },
346+ }
347+ store := & stubStore {tok : stored }
348+ base := oauth2 .StaticTokenSource ((& oauth2.Token {
349+ AccessToken : "access" ,
350+ RefreshToken : "same-token" ,
351+ }).WithExtra (map [string ]any {
352+ "scope" : "https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/directory.readonly" ,
353+ }))
354+ ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored ,
"contacts" )
355+
356+ if _ , err := ts .Token (); err != nil {
357+ t .Fatalf ("Token: %v" , err )
358+ }
359+
360+ if store .setCalls != 1 {
361+ t .Fatalf ("expected 1 SetToken call, got %d" , store .setCalls )
362+ }
363+
364+ wantServices := []string {"calendar" }
365+ if ! reflect .DeepEqual (store .lastSet .Services , wantServices ) {
366+ t .Fatalf ("services=%#v want %#v" , store .lastSet .Services , wantServices )
367+ }
368+
369+ wantScopes := []string {
370+ "https://www.googleapis.com/auth/calendar" ,
371+ "https://www.googleapis.com/auth/directory.readonly" ,
372+ }
373+ if ! reflect .DeepEqual (store .lastSet .Scopes , wantScopes ) {
374+ t .Fatalf ("scopes=%#v want %#v" , store .lastSet .Scopes , wantScopes )
375+ }
376+ }
377+
378+ func TestPersistingTokenSource_DoesNotPersistRequestedScopeWithoutObservedGrant (t * testing.T ) {
379+ stored := secrets.Token {
380+ 381+ RefreshToken : "same-token" ,
382+ AccessToken : "access" ,
383+ Services : []string {"calendar" },
384+ Scopes : []string {"https://www.googleapis.com/auth/calendar" },
385+ }
386+ store := & stubStore {tok : stored }
387+ base := oauth2 .StaticTokenSource ((& oauth2.Token {
388+ AccessToken : "access" ,
389+ RefreshToken : "same-token" ,
390+ }).WithExtra (map [string ]any {
391+ "scope" : "https://www.googleapis.com/auth/calendar" ,
392+ }))
393+ ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored ,
"gmail" )
283394
284395 if _ , err := ts .Token (); err != nil {
285396 t .Fatalf ("Token: %v" , err )
@@ -299,7 +410,7 @@ func TestPersistingTokenSource_BackfillsSubjectFromIDToken(t *testing.T) {
299410 }).WithExtra (map [string ]any {
300411 "id_token" :
unsignedIDTokenForTest (
t ,
"sub-123" ,
"[email protected] " ),
301412 }))
302- ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored )
413+ ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored , "" )
303414
304415 if _ , err := ts .Token (); err != nil {
305416 t .Fatalf ("Token: %v" , err )
@@ -343,7 +454,7 @@ func TestPersistingTokenSource_MigratesRenamedEmailFromIDToken(t *testing.T) {
343454 }).WithExtra (map [string ]any {
344455 "id_token" :
unsignedIDTokenForTest (
t ,
"sub-123" ,
"[email protected] " ),
345456 }))
346- ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored )
457+ ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored , "" )
347458
348459 if _ , err := ts .Token (); err != nil {
349460 t .Fatalf ("Token: %v" , err )
@@ -400,7 +511,7 @@ func TestPersistingTokenSource_PersistFailureIsNonFatal(t *testing.T) {
400511 stored := secrets.
Token {
Email :
"[email protected] " ,
RefreshToken :
"old-token" }
401512 store := & stubStore {tok : stored , setErr : errBoom }
402513 base := oauth2 .StaticTokenSource (& oauth2.Token {AccessToken : "access" , RefreshToken : "new-token" })
403- ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored )
514+ ts := newPersistingTokenSource (
base ,
store ,
config .
DefaultClientName ,
"[email protected] " ,
stored , "" )
404515
405516 tok , err := ts .Token ()
406517 if err != nil {
0 commit comments