From 70ea8957c6a40a9c05df4dca6dcf11bb7504eb4b Mon Sep 17 00:00:00 2001 From: John Westerlund Date: Wed, 4 Mar 2026 19:15:13 +0100 Subject: [PATCH] fix(auth): restrict Keep service account to Keep API calls only When a Keep-specific service account file (keep-sa-*.json) exists, tokenSourceForServiceAccountScopes falls back to it for all API calls, not just Keep. This causes 401 errors on Calendar, Gmail, Drive, and other services that should use OAuth. Only use keep-sa and legacy Keep SA files when serviceLabel is "keep", allowing other services to fall through to OAuth authentication. Co-Authored-By: Claude Opus 4.6 --- internal/googleapi/client.go | 2 +- internal/googleapi/service_account.go | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/internal/googleapi/client.go b/internal/googleapi/client.go index 40a77d73..1642d407 100644 --- a/internal/googleapi/client.go +++ b/internal/googleapi/client.go @@ -99,7 +99,7 @@ func optionsForAccountScopes(ctx context.Context, serviceLabel string, email str var ts oauth2.TokenSource - if serviceAccountTS, saPath, ok, err := tokenSourceForServiceAccountScopes(ctx, email, scopes); err != nil { + if serviceAccountTS, saPath, ok, err := tokenSourceForServiceAccountScopes(ctx, serviceLabel, email, scopes); err != nil { return nil, fmt.Errorf("service account token source: %w", err) } else if ok { slog.Debug("using service account credentials", "email", email, "path", saPath) diff --git a/internal/googleapi/service_account.go b/internal/googleapi/service_account.go index 021963c5..6455b54e 100644 --- a/internal/googleapi/service_account.go +++ b/internal/googleapi/service_account.go @@ -25,7 +25,7 @@ var newServiceAccountTokenSource = func(ctx context.Context, keyJSON []byte, sub return cfg.TokenSource(ctx), nil } -func tokenSourceForServiceAccountScopes(ctx context.Context, email string, scopes []string) (oauth2.TokenSource, string, bool, error) { +func tokenSourceForServiceAccountScopes(ctx context.Context, serviceLabel string, email string, scopes []string) (oauth2.TokenSource, string, bool, error) { saPath, err := config.ServiceAccountPath(email) if err != nil { return nil, "", false, fmt.Errorf("service account path: %w", err) @@ -45,6 +45,11 @@ func tokenSourceForServiceAccountScopes(ctx context.Context, email string, scope return nil, "", false, fmt.Errorf("read service account key: %w", readErr) } + // Keep-specific service account files should only be used for Keep. + if serviceLabel != "keep" { + return nil, "", false, nil + } + // Backwards compatibility: Keep used a dedicated stored service account file. keepSAPath, keepErr := config.KeepServiceAccountPath(email) if keepErr == nil {