golang / oauth2

Go OAuth2
https://golang.org/x/oauth2
BSD 3-Clause "New" or "Revised" License
5.38k stars 990 forks source link

Need an interface for oauth2.Config and clientcredentials.Config #394

Open glevine opened 5 years ago

glevine commented 5 years ago

I'd like to be able to pass either an oauth2.Config or clientcredentials.Config into a function and produce an *http.Client. This would help with supporting either two- or three-legged OAuth in an API client.

type APIClient struct {
    httpClient *http.Client
}

func (client *APIClient) WithCredentials(creds oauth2.SomeConfigInterface) *APIClient {
    client.httpClient = creds.Client(...)
    return client
}

func (client *APIClient) Get(...) (*http.Response, err) {
    ...
}

client := APIClient{}
resp, err := client.WithCredentials(&oauth2.Config{...}).Get(...)
// OR
resp, err := client.WithCredentials(&clientcredentials.Config{...}).Get(...)

But I don't see any methods that share the same signatures. And I haven't found a way to work around that cleanly.

Is there an existing pattern that allows me to do this and I'm just not seeing it?

glevine commented 5 years ago

After another look, I realized I could use the oauth2.TokenSource interface.

type APIClient struct {
    src oauth2.TokenSource 
}

func (client *APIClient) WithTokenSource(src oauth2.TokenSource) *APIClient {
    client.src = src
    return client
}

func (client *APIClient) Get(ctx context.Context, ...) (*http.Response, err) {
    httpClient := oauth2.NewClient(ctx, client.src)
    return httpClient.Get(...)
}

client := APIClient{}
config := &oauth2.Config{...}
token := &oauth2.Token{...}
ts := conf.TokenSource(ctx, token)
resp, err := client.WithTokenSource(ts).Get(...)
// OR
config := &clientcredentials.Config{...}
ts := conf.TokenSource(ctx)
resp, err := client.WithTokenSource(ts).Get(...)