Skip to content

Commit a4da757

Browse files
Merge pull request #68 from with-joy/fix/67-auto-token-refresh
fix(auth): implement automatic OAuth token refresh
2 parents 9357896 + e630971 commit a4da757

2 files changed

Lines changed: 438 additions & 8 deletions

File tree

pkg/client/client.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"time"
1414

1515
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
16+
"github.com/DataDog/pup/pkg/auth/dcr"
1617
"github.com/DataDog/pup/pkg/auth/storage"
1718
"github.com/DataDog/pup/pkg/config"
1819
"github.com/DataDog/pup/pkg/useragent"
@@ -25,6 +26,12 @@ type Client struct {
2526
api *datadog.APIClient
2627
}
2728

29+
// Test hooks — overridden in tests to inject fakes
30+
var (
31+
getStorageFunc = func() (storage.Storage, error) { return storage.GetStorage(nil) }
32+
newDCRClientFunc = func(site string) *dcr.Client { return dcr.NewClient(site) }
33+
)
34+
2835
// New creates a new Datadog API client
2936
// Authentication priority:
3037
// 1. OAuth2 tokens (if available and valid)
@@ -45,16 +52,31 @@ func NewWithOptions(cfg *config.Config, forceAPIKeys bool) (*Client, error) {
4552

4653
if !forceAPIKeys {
4754
// Try OAuth2 tokens first (preferred method)
48-
store, err := storage.GetStorage(nil)
55+
store, err := getStorageFunc()
4956
if err == nil {
5057
tokens, err := store.LoadTokens(cfg.Site)
51-
if err == nil && tokens != nil && !tokens.IsExpired() {
52-
// Use OAuth2 Bearer token authentication
53-
ctx = context.WithValue(
54-
context.Background(),
55-
datadog.ContextAccessToken,
56-
tokens.AccessToken,
57-
)
58+
if err == nil && tokens != nil {
59+
// Auto-refresh: if token is expired but refresh token is available, refresh it
60+
if tokens.IsExpired() && tokens.RefreshToken != "" {
61+
creds, credsErr := store.LoadClientCredentials(cfg.Site)
62+
if credsErr == nil && creds != nil {
63+
dcrClient := newDCRClientFunc(cfg.Site)
64+
newTokens, refreshErr := dcrClient.RefreshToken(tokens.RefreshToken, creds)
65+
if refreshErr == nil {
66+
_ = store.SaveTokens(cfg.Site, newTokens)
67+
tokens = newTokens
68+
}
69+
}
70+
}
71+
72+
if !tokens.IsExpired() {
73+
// Use OAuth2 Bearer token authentication
74+
ctx = context.WithValue(
75+
context.Background(),
76+
datadog.ContextAccessToken,
77+
tokens.AccessToken,
78+
)
79+
}
5880
}
5981
}
6082
}

0 commit comments

Comments
 (0)