Skip to content

fix(auth): implement automatic OAuth token refresh#68

Merged
platinummonkey merged 1 commit intoDataDog:mainfrom
with-joy:fix/67-auto-token-refresh
Feb 15, 2026
Merged

fix(auth): implement automatic OAuth token refresh#68
platinummonkey merged 1 commit intoDataDog:mainfrom
with-joy:fix/67-auto-token-refresh

Conversation

@with-joy
Copy link
Contributor

Summary

Implement automatic OAuth token refresh when access tokens expire, eliminating the need
for users to manually run pup auth refresh or pup auth login every hour.

Changes

  • Add auto-refresh logic to NewWithOptions in pkg/client/client.go — when a token is expired
    and a refresh token exists, call dcr.Client.RefreshToken() and persist the new tokens
  • Add test hooks (getStorageFunc, newDCRClientFunc) for dependency injection in tests
  • Add 8 unit tests in pkg/client/client_oauth_test.go covering all refresh paths

Test plan

  • TestNewWithOptions_ValidToken_UsesOAuth — fresh token uses OAuth directly
  • TestNewWithOptions_ExpiredToken_NoRefreshToken_FallsBackToAPIKeys — no refresh token, falls back
  • TestNewWithOptions_ExpiredToken_NoClientCreds_FallsBackToAPIKeys — missing creds, falls back
  • TestNewWithOptions_ExpiredToken_RefreshFails_FallsBackToAPIKeys — server rejects, falls back
  • TestNewWithOptions_ExpiredToken_RefreshSucceeds_UsesNewToken — uses refreshed token
  • TestNewWithOptions_ExpiredToken_RefreshSucceeds_PersistsNewToken — saves refreshed token
  • TestNewWithOptions_ExpiredToken_NoAPIKeys_ReturnsError — clear error when no auth available
  • TestNewWithOptions_ForceAPIKeys_SkipsOAuth — forceAPIKeys bypasses OAuth entirely
  • Manual verification: expired token → pup monitors list succeeds after silent refresh

Closes #67

Made with Cursor

…tokens

When an access token is expired and a valid refresh token exists, the
client now automatically refreshes via the DCR token endpoint before
falling back to API keys. This matches the behavior documented in
docs/OAUTH2.md and docs/ARCHITECTURE.md.

- Add auto-refresh logic to NewWithOptions in pkg/client/client.go
- Add test hooks (getStorageFunc, newDCRClientFunc) for dependency injection
- Add 8 unit tests covering all refresh paths (success, failure, fallback)

Closes DataDog#67

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@with-joy with-joy requested a review from a team as a code owner February 15, 2026 20:29
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e630971be3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

dcrClient := newDCRClientFunc(cfg.Site)
newTokens, refreshErr := dcrClient.RefreshToken(tokens.RefreshToken, creds)
if refreshErr == nil {
_ = store.SaveTokens(cfg.Site, newTokens)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Surface refresh token save failures

When refresh succeeds, the code ignores store.SaveTokens errors and continues with the in-memory token. This creates a latent auth regression whenever keychain/file writes fail (e.g., locked keychain, permission issues): the current command appears to work, but the next process reloads stale tokens and may fail to refresh (especially if the refresh token rotated), forcing unexpected re-login or auth errors. This path was introduced by the new auto-refresh flow, so persistence failures should be handled explicitly instead of being silently dropped.

Useful? React with 👍 / 👎.

@platinummonkey platinummonkey merged commit a4da757 into DataDog:main Feb 15, 2026
5 checks passed
@with-joy with-joy deleted the fix/67-auto-token-refresh branch February 15, 2026 23:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(auth): automatic OAuth token refresh not implemented — forces re-login every hour

2 participants