github.com/wanddynosios/cli/v8@v8.7.9-0.20240221182337-1a92e3a7017f/api/router/wrapper/uaa_authentication.go (about)

     1  package wrapper
     2  
     3  import (
     4  	"code.cloudfoundry.org/cli/api/router"
     5  	"code.cloudfoundry.org/cli/api/router/routererror"
     6  	"code.cloudfoundry.org/cli/api/uaa"
     7  )
     8  
     9  //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . 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 go run github.com/maxbrunsfeld/counterfeiter/v6 . 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 router.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  // Make adds authentication headers to the passed in request and then calls the
    44  // wrapped connection's Make. If the client is not set on the wrapper, it will
    45  // not add any header or handle any authentication errors.
    46  func (t *UAAAuthentication) Make(request *router.Request, passedResponse *router.Response) error {
    47  	if t.client == nil {
    48  		return t.connection.Make(request, passedResponse)
    49  	}
    50  
    51  	request.Header.Set("Authorization", t.cache.AccessToken())
    52  
    53  	requestErr := t.connection.Make(request, passedResponse)
    54  	if _, ok := requestErr.(routererror.InvalidAuthTokenError); ok {
    55  		tokens, err := t.client.RefreshAccessToken(t.cache.RefreshToken())
    56  		if err != nil {
    57  			return err
    58  		}
    59  
    60  		t.cache.SetAccessToken(tokens.AuthorizationToken())
    61  		t.cache.SetRefreshToken(tokens.RefreshToken)
    62  
    63  		if request.Body != nil {
    64  			err = request.ResetBody()
    65  			if err != nil {
    66  				return err
    67  			}
    68  		}
    69  		request.Header.Set("Authorization", t.cache.AccessToken())
    70  		requestErr = t.connection.Make(request, passedResponse)
    71  	}
    72  
    73  	return requestErr
    74  }
    75  
    76  // SetClient sets the UAA client that the wrapper will use.
    77  func (t *UAAAuthentication) SetClient(client UAAClient) {
    78  	t.client = client
    79  }
    80  
    81  // Wrap sets the connection on the UAAAuthentication and returns itself
    82  func (t *UAAAuthentication) Wrap(innerconnection router.Connection) router.Connection {
    83  	t.connection = innerconnection
    84  	return t
    85  }