Skip to content

Commit 0bbd388

Browse files
wesmclaude
andcommitted
Add regression test for token saved under original identifier
Verifies that when the canonical Gmail address differs from the user-supplied identifier (dotted alias, case, googlemail.com), the token is saved under the original identifier — not the canonical one. This is the key invariant that prevents breaking HasToken/TokenSource lookups elsewhere in the app. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fcb77e4 commit 0bbd388

File tree

1 file changed

+48
-0
lines changed

1 file changed

+48
-0
lines changed

internal/oauth/oauth_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,54 @@ func TestNewCallbackHandler(t *testing.T) {
582582
}
583583
}
584584

585+
// TestTokenSavedUnderOriginalIdentifier verifies that when the canonical
586+
// Gmail address differs from the user-supplied identifier (e.g. dotted
587+
// alias), the token is saved under the original identifier — not the
588+
// canonical one. This is the key invariant enforced by authorize():
589+
// sameGoogleAccount() accepts the alias, and saveToken() uses the
590+
// original email.
591+
//
592+
// Regression test: a previous version saved under canonicalEmail,
593+
// breaking HasToken/TokenSource lookups elsewhere in the app.
594+
func TestTokenSavedUnderOriginalIdentifier(t *testing.T) {
595+
mgr := setupTestManager(t, Scopes)
596+
597+
token := &oauth2.Token{
598+
AccessToken: "test-access-token",
599+
TokenType: "Bearer",
600+
Expiry: time.Now().Add(time.Hour),
601+
}
602+
603+
// Simulate what authorize() does: validate via sameGoogleAccount,
604+
// then save under the original identifier.
605+
inputEmail := "first.last@gmail.com"
606+
canonicalEmail := "firstlast@gmail.com"
607+
608+
if !sameGoogleAccount(inputEmail, canonicalEmail) {
609+
t.Fatalf("sameGoogleAccount(%q, %q) = false, want true",
610+
inputEmail, canonicalEmail)
611+
}
612+
613+
// Save under original identifier (the authorize() contract)
614+
if err := mgr.saveToken(inputEmail, token, Scopes); err != nil {
615+
t.Fatalf("saveToken: %v", err)
616+
}
617+
618+
// Token must be loadable under the original identifier
619+
loaded, err := mgr.loadToken(inputEmail)
620+
if err != nil {
621+
t.Fatalf("loadToken(%q) failed: %v", inputEmail, err)
622+
}
623+
if loaded.AccessToken != "test-access-token" {
624+
t.Errorf("wrong access token: got %q", loaded.AccessToken)
625+
}
626+
627+
// Token must NOT exist under the canonical email
628+
if _, err := mgr.loadToken(canonicalEmail); err == nil {
629+
t.Errorf("token should NOT exist under canonical %q", canonicalEmail)
630+
}
631+
}
632+
585633
func TestSameGoogleAccount(t *testing.T) {
586634
t.Parallel()
587635

0 commit comments

Comments
 (0)