github.com/liamawhite/cli-with-i18n@v6.32.1-0.20171122084555-dede0a5c3448+incompatible/api/cloudcontroller/wrapper/uaa_authentication.go (about)

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