github.com/dcarley/cf-cli@v6.24.1-0.20170220111324-4225ff346898+incompatible/api/uaa/wrapper/uaa_authentication.go (about) 1 package wrapper 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "net/http" 7 "strings" 8 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 uaa.Connection 33 client UAAClient 34 cache TokenCache 35 } 36 37 // NewUAAAuthentication returns a pointer to a UAAAuthentication wrapper with 38 // the client and 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 uaa.Connection) uaa.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 *uaa.Response) error { 55 var err error 56 var rawRequestBody []byte 57 58 if request.Body != nil { 59 rawRequestBody, err = ioutil.ReadAll(request.Body) 60 defer request.Body.Close() 61 if err != nil { 62 return err 63 } 64 65 request.Body = ioutil.NopCloser(bytes.NewBuffer(rawRequestBody)) 66 67 // The authentication header is not added to the token refresh request. 68 if strings.Contains(request.URL.String(), "/oauth/token") && 69 request.Method == http.MethodPost && 70 strings.Contains(string(rawRequestBody), "grant_type=refresh_token") { 71 return t.connection.Make(request, passedResponse) 72 } 73 } 74 75 request.Header.Set("Authorization", t.cache.AccessToken()) 76 77 err = t.connection.Make(request, passedResponse) 78 if _, ok := err.(uaa.InvalidAuthTokenError); ok { 79 var token uaa.RefreshToken 80 token, err = t.client.RefreshAccessToken(t.cache.RefreshToken()) 81 if err != nil { 82 return err 83 } 84 85 t.cache.SetAccessToken(token.AuthorizationToken()) 86 t.cache.SetRefreshToken(token.RefreshToken) 87 88 if rawRequestBody != nil { 89 request.Body = ioutil.NopCloser(bytes.NewBuffer(rawRequestBody)) 90 } 91 request.Header.Set("Authorization", t.cache.AccessToken()) 92 return t.connection.Make(request, passedResponse) 93 } 94 95 return err 96 }