Skip to content

Commit

Permalink
add ProviderClient.Reauthenticate() function
Browse files Browse the repository at this point in the history
If a user wants to do their own HTTP requests and reauthenticate in case
of 401 responses, they can already use ProviderClient.ReauthFunc(), but
that function is not thread-safe. This commit provides a safer
alternative by pulling the relevant piece of code out of
ProviderClient.Request().
  • Loading branch information
majewsky committed Jan 28, 2018
1 parent 4a3f5ae commit f0a5d28
Showing 1 changed file with 31 additions and 15 deletions.
46 changes: 31 additions & 15 deletions provider_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,36 @@ func (client *ProviderClient) SetToken(t string) {
client.TokenID = t
}

//Reauthenticate calls client.ReauthFunc in a thread-safe way. If this is
//called because of a 401 response, the caller may pass the previous token. In
//this case, the reauthentication can be skipped if another thread has already
//reauthenticated in the meantime. If no previous token is known, an empty
//string should be passed instead to force unconditional reauthentication.
func (client *ProviderClient) Reauthenticate(previousToken string) (err error) {
if client.ReauthFunc == nil {
return nil
}

if client.mut == nil {
return client.ReauthFunc()
}
client.mut.Lock()
defer client.mut.Unlock()

client.reauthmut.Lock()
client.reauthmut.reauthing = true
client.reauthmut.Unlock()

if previousToken == "" || client.TokenID == previousToken {
err = client.ReauthFunc()
}

client.reauthmut.Lock()
client.reauthmut.reauthing = false
client.reauthmut.Unlock()
return
}

// RequestOpts customizes the behavior of the provider.Request() method.
type RequestOpts struct {
// JSONBody, if provided, will be encoded as JSON and used as the body of the HTTP request. The
Expand Down Expand Up @@ -254,21 +284,7 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)
}
case http.StatusUnauthorized:
if client.ReauthFunc != nil {
if client.mut != nil {
client.mut.Lock()
client.reauthmut.Lock()
client.reauthmut.reauthing = true
client.reauthmut.Unlock()
if curtok := client.TokenID; curtok == prereqtok {
err = client.ReauthFunc()
}
client.reauthmut.Lock()
client.reauthmut.reauthing = false
client.reauthmut.Unlock()
client.mut.Unlock()
} else {
err = client.ReauthFunc()
}
err = client.Reauthenticate(prereqtok)
if err != nil {
e := &ErrUnableToReauthenticate{}
e.ErrOriginal = respErr
Expand Down

0 comments on commit f0a5d28

Please sign in to comment.