github.com/dcarley/cf-cli@v6.24.1-0.20170220111324-4225ff346898+incompatible/api/cloudcontroller/wrapper/uaa_authentication.go (about)

     1  package wrapper
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"net/http"
     7  
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller"
     9  	"code.cloudfoundry.org/cli/api/uaa"
    10  )
    11  
    12  //go:generate counterfeiter . UAAClient
    13  
    14  // UAAClient is the interface for getting a valid access token
    15  type UAAClient interface {
    16  	RefreshAccessToken(refreshToken string) (uaa.RefreshToken, error)
    17  }
    18  
    19  //go:generate counterfeiter . TokenCache
    20  
    21  // TokenCache is where the UAA token information is stored.
    22  type TokenCache interface {
    23  	AccessToken() string
    24  	RefreshToken() string
    25  	SetAccessToken(token string)
    26  	SetRefreshToken(token string)
    27  }
    28  
    29  // UAAAuthentication wraps connections and adds authentication headers to all
    30  // requests
    31  type UAAAuthentication struct {
    32  	connection cloudcontroller.Connection
    33  	client     UAAClient
    34  	cache      TokenCache
    35  }
    36  
    37  // NewUAAAuthentication returns a pointer to a UAAAuthentication wrapper with
    38  // the client and a token cache.
    39  func NewUAAAuthentication(client UAAClient, cache TokenCache) *UAAAuthentication {
    40  	return &UAAAuthentication{
    41  		client: client,
    42  		cache:  cache,
    43  	}
    44  }
    45  
    46  // Wrap sets the connection on the UAAAuthentication and returns itself
    47  func (t *UAAAuthentication) Wrap(innerconnection cloudcontroller.Connection) cloudcontroller.Connection {
    48  	t.connection = innerconnection
    49  	return t
    50  }
    51  
    52  // Make adds authentication headers to the passed in request and then calls the
    53  // wrapped connection's Make
    54  func (t *UAAAuthentication) Make(request *http.Request, passedResponse *cloudcontroller.Response) error {
    55  	var (
    56  		err            error
    57  		rawRequestBody []byte
    58  	)
    59  
    60  	if request.Body != nil {
    61  		rawRequestBody, err = ioutil.ReadAll(request.Body)
    62  		defer request.Body.Close()
    63  		if err != nil {
    64  			return err
    65  		}
    66  		request.Body = ioutil.NopCloser(bytes.NewBuffer(rawRequestBody))
    67  	}
    68  
    69  	request.Header.Set("Authorization", t.cache.AccessToken())
    70  
    71  	err = t.connection.Make(request, passedResponse)
    72  	if _, ok := err.(cloudcontroller.InvalidAuthTokenError); ok {
    73  		var token uaa.RefreshToken
    74  		token, err = t.client.RefreshAccessToken(t.cache.RefreshToken())
    75  		if err != nil {
    76  			return err
    77  		}
    78  
    79  		t.cache.SetAccessToken(token.AuthorizationToken())
    80  		t.cache.SetRefreshToken(token.RefreshToken)
    81  
    82  		if rawRequestBody != nil {
    83  			request.Body = ioutil.NopCloser(bytes.NewBuffer(rawRequestBody))
    84  		}
    85  		request.Header.Set("Authorization", t.cache.AccessToken())
    86  		err = t.connection.Make(request, passedResponse)
    87  	}
    88  
    89  	return err
    90  }