Skip to content

Commit

Permalink
Add ability to pass a custom audience when using client credentials
Browse files Browse the repository at this point in the history
  • Loading branch information
sergiught committed Aug 23, 2022
1 parent 684b8eb commit d6667d4
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 3 deletions.
21 changes: 18 additions & 3 deletions internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,29 @@ func Wrap(base *http.Client, tokenSource oauth2.TokenSource, options ...Option)

// OAuth2ClientCredentials sets the oauth2 client credentials.
func OAuth2ClientCredentials(ctx context.Context, uri, clientID, clientSecret string) oauth2.TokenSource {
return (&clientcredentials.Config{
audience := uri + "/api/v2/"
return OAuth2ClientCredentialsAndAudience(ctx, uri, clientID, clientSecret, audience)
}

// OAuth2ClientCredentialsAndAudience sets the oauth2
// client credentials with a custom audience.
func OAuth2ClientCredentialsAndAudience(
ctx context.Context,
uri,
clientID,
clientSecret,
audience string,
) oauth2.TokenSource {
cfg := &clientcredentials.Config{
ClientID: clientID,
ClientSecret: clientSecret,
TokenURL: uri + "/oauth/token",
EndpointParams: url.Values{
"audience": {uri + "/api/v2/"},
"audience": []string{audience},
},
}).TokenSource(ctx)
}

return cfg.TokenSource(ctx)
}

// StaticToken sets a static token to be used for oauth2.
Expand Down
35 changes: 35 additions & 0 deletions internal/client/client_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package client

import (
"context"
"fmt"
"io"
"net/http"
"net/http/httptest"
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestWrapRateLimit(t *testing.T) {
Expand Down Expand Up @@ -58,3 +62,34 @@ func TestWrapUserAgent(t *testing.T) {
c := Wrap(s.Client(), StaticToken(""), WithUserAgent(UserAgent))
c.Get(s.URL)
}

func TestOAuth2ClientCredentialsAndAudience(t *testing.T) {
const expectedAudience = "myAudience"

handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/oauth/token":
requestBody, err := io.ReadAll(r.Body)
assert.NoError(t, err)
assert.Contains(t, string(requestBody), expectedAudience)

w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"access_token":"someToken","token_type":"Bearer"}`))
default:
http.NotFound(w, r)
}
})
testServer := httptest.NewServer(handler)

tokenSource := OAuth2ClientCredentialsAndAudience(
context.Background(),
testServer.URL,
"clientID",
"clientSecret",
expectedAudience,
)

token, err := tokenSource.Token()
assert.NoError(t, err)
assert.Equal(t, "someToken", token.AccessToken)
}
14 changes: 14 additions & 0 deletions management/management_option.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@ func WithClientCredentials(clientID, clientSecret string) Option {
}
}

// WithClientCredentialsAndAudience configures management to authenticate using the client
// credentials authentication flow and a custom audience.
func WithClientCredentialsAndAudience(clientID, clientSecret, audience string) Option {
return func(m *Management) {
m.tokenSource = client.OAuth2ClientCredentialsAndAudience(
m.ctx,
m.url.String(),
clientID,
clientSecret,
audience,
)
}
}

// WithStaticToken configures management to authenticate using a static
// authentication token.
func WithStaticToken(token string) Option {
Expand Down

0 comments on commit d6667d4

Please sign in to comment.