Skip to content

Commit 61d70f8

Browse files
authored
[extension/oauth2clientauth] Add Token expiry buffer for oauth2clientauthextension (#37334)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description Adds an expiry_buffer config to the oauth2client extension, allowing token refresh before expiration. The default buffer is set to 5 m, preventing authentication failures due to token expiration. <!-- Issue number (e.g. #1234) or full URL to issue, if applicable. --> #### Link to tracking issue Fixes #35148 <!--Describe what testing was performed and which tests were added.--> #### Testing passes tests. <!--Describe the documentation added.--> #### Documentation The README has been updated to include the expiry_buffer config option, with instructions on how to use it and its default value. <!--Please delete paragraphs that you did not use before submitting.-->
1 parent b589bef commit 61d70f8

File tree

10 files changed

+54
-3
lines changed

10 files changed

+54
-3
lines changed

.chloggen/oauth2-expiry-buffer.yaml

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: extension/oauth2clientauth
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Add `expiry_buffer` config to `oauth2client` extension, allowing token refresh before expiration with a default buffer of 5 minutes.
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [35148]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext: |
19+
- Prevents authentication failures by refreshing the token early.
20+
- The default expiry buffer is set to 5 minutes, and users can adjust it as needed.
21+
22+
# If your change doesn't affect end users or the exported elements of any package,
23+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
24+
# Optional: The change log or logs in which this entry should be included.
25+
# e.g. '[user]' or '[user, api]'
26+
# Include 'user' if the change is relevant to end users.
27+
# Include 'api' if there is a change to a library API.
28+
# Default: '[user]'
29+
change_logs: [user]

extension/oauth2clientauthextension/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ extensions:
3838
key_file: keyfile
3939
# timeout for the token client
4040
timeout: 2s
41+
# buffer time before token expiry to refresh
42+
expiry_buffer: 10s
4143

4244
receivers:
4345
hostmetrics:
@@ -84,5 +86,6 @@ Following are the configuration fields
8486
- [**scopes**](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3) - **Optional** optional requested permissions associated for the client.
8587
- [**timeout**](https://golang.org/src/net/http/client.go#L90) - **Optional** specifies the timeout on the underlying client to authorization server for fetching the tokens (initial and while refreshing).
8688
This is optional and not setting this configuration implies there is no timeout on the client.
89+
- **expiry_buffer** - **Optional** Specifies the time buffer to refresh the access token before it expires, preventing authentication failures due to token expiration. The default value is 5m.
8790

8891
For more information on client side TLS settings, see [configtls README](https://github.com/open-telemetry/opentelemetry-collector/tree/main/config/configtls).

extension/oauth2clientauthextension/clientcredentialsconfig.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"os"
1010
"strings"
11+
"time"
1112

1213
"go.uber.org/multierr"
1314
"golang.org/x/oauth2"
@@ -36,6 +37,7 @@ type clientCredentialsConfig struct {
3637

3738
ClientIDFile string
3839
ClientSecretFile string
40+
ExpiryBuffer time.Duration
3941
}
4042

4143
type clientCredentialsTokenSource struct {
@@ -90,7 +92,7 @@ func (c *clientCredentialsConfig) createConfig() (*clientcredentials.Config, err
9092
}
9193

9294
func (c *clientCredentialsConfig) TokenSource(ctx context.Context) oauth2.TokenSource {
93-
return oauth2.ReuseTokenSource(nil, clientCredentialsTokenSource{ctx: ctx, config: c})
95+
return oauth2.ReuseTokenSourceWithExpiry(nil, clientCredentialsTokenSource{ctx: ctx, config: c}, c.ExpiryBuffer)
9496
}
9597

9698
func (ts clientCredentialsTokenSource) Token() (*oauth2.Token, error) {

extension/oauth2clientauthextension/config.go

+3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ type Config struct {
5353
// Timeout parameter configures `http.Client.Timeout` for the underneath client to authorization
5454
// server while fetching and refreshing tokens.
5555
Timeout time.Duration `mapstructure:"timeout,omitempty"`
56+
57+
// ExpiryBuffer specifies the time buffer before token expiry to refresh it.
58+
ExpiryBuffer time.Duration `mapstructure:"expiry_buffer,omitempty"`
5659
}
5760

5861
var _ component.Config = (*Config)(nil)

extension/oauth2clientauthextension/config_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func TestLoadConfig(t *testing.T) {
3535
Scopes: []string{"api.metrics"},
3636
TokenURL: "https://example.com/oauth2/default/v1/token",
3737
Timeout: time.Second,
38+
ExpiryBuffer: 5 * time.Minute,
3839
},
3940
},
4041
{
@@ -55,6 +56,7 @@ func TestLoadConfig(t *testing.T) {
5556
InsecureSkipVerify: false,
5657
ServerName: "",
5758
},
59+
ExpiryBuffer: 15 * time.Second,
5860
},
5961
},
6062
{

extension/oauth2clientauthextension/extension.go

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ func newClientAuthenticator(cfg *Config, logger *zap.Logger) (*clientAuthenticat
5555
},
5656
ClientIDFile: cfg.ClientIDFile,
5757
ClientSecretFile: cfg.ClientSecretFile,
58+
ExpiryBuffer: cfg.ExpiryBuffer,
5859
},
5960
logger: logger,
6061
client: &http.Client{

extension/oauth2clientauthextension/extension_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net/http/httptest"
1010
"net/url"
1111
"testing"
12+
"time"
1213

1314
"github.com/stretchr/testify/assert"
1415
"github.com/stretchr/testify/require"
@@ -42,6 +43,7 @@ func TestOAuthClientSettings(t *testing.T) {
4243
TokenURL: "https://example.com/v1/token",
4344
Scopes: []string{"resource.read"},
4445
Timeout: 2,
46+
ExpiryBuffer: 10 * time.Second,
4547
TLSSetting: configtls.ClientConfig{
4648
Config: configtls.Config{
4749
CAFile: testCAFile,
@@ -63,6 +65,7 @@ func TestOAuthClientSettings(t *testing.T) {
6365
TokenURL: "https://example.com/v1/token",
6466
Scopes: []string{"resource.read"},
6567
Timeout: 2,
68+
ExpiryBuffer: 15 * time.Second,
6669
TLSSetting: configtls.ClientConfig{
6770
Config: configtls.Config{
6871
CAFile: testCAFile,
@@ -91,6 +94,7 @@ func TestOAuthClientSettings(t *testing.T) {
9194
assert.EqualValues(t, test.settings.ClientSecret, rc.clientCredentials.ClientSecret)
9295
assert.Equal(t, test.settings.ClientID, rc.clientCredentials.ClientID)
9396
assert.Equal(t, test.settings.Timeout, rc.client.Timeout)
97+
assert.Equal(t, test.settings.ExpiryBuffer, rc.clientCredentials.ExpiryBuffer)
9498
assert.Equal(t, test.settings.EndpointParams, rc.clientCredentials.EndpointParams)
9599

96100
// test tls settings

extension/oauth2clientauthextension/factory.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package oauth2clientauthextension // import "github.com/open-telemetry/opentelem
55

66
import (
77
"context"
8+
"time"
89

910
"go.opentelemetry.io/collector/component"
1011
"go.opentelemetry.io/collector/extension"
@@ -24,7 +25,9 @@ func NewFactory() extension.Factory {
2425
}
2526

2627
func createDefaultConfig() component.Config {
27-
return &Config{}
28+
return &Config{
29+
ExpiryBuffer: 5 * time.Minute,
30+
}
2831
}
2932

3033
func createExtension(_ context.Context, set extension.Settings, cfg component.Config) (extension.Extension, error) {

extension/oauth2clientauthextension/factory_test.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package oauth2clientauthextension
66
import (
77
"context"
88
"testing"
9+
"time"
910

1011
"github.com/stretchr/testify/assert"
1112
"go.opentelemetry.io/collector/component/componenttest"
@@ -14,7 +15,9 @@ import (
1415

1516
func TestCreateDefaultConfig(t *testing.T) {
1617
// prepare and test
17-
expected := &Config{}
18+
expected := &Config{
19+
ExpiryBuffer: 5 * time.Minute,
20+
}
1821

1922
// test
2023
cfg := createDefaultConfig()

extension/oauth2clientauthextension/testdata/config.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ oauth2client/withtls:
1313
token_url: https://example2.com/oauth2/default/v1/token
1414
scopes: ["api.metrics"]
1515
timeout: 1s
16+
expiry_buffer: 15s
1617
# tls settings for the token client
1718
tls:
1819
insecure: true

0 commit comments

Comments
 (0)