github.com/lukasheimann/cloudfoundrycli@v7.1.0+incompatible/api/uaa/auth_test.go (about)

     1  package uaa_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"net/http"
     7  	"net/url"
     8  
     9  	. "code.cloudfoundry.org/cli/api/uaa"
    10  	"code.cloudfoundry.org/cli/api/uaa/constant"
    11  	"code.cloudfoundry.org/cli/api/uaa/uaafakes"
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  	. "github.com/onsi/gomega/ghttp"
    15  )
    16  
    17  var _ = Describe("Auth", func() {
    18  	var (
    19  		client      *Client
    20  		credentials map[string]string
    21  
    22  		origin    string
    23  		grantType constant.GrantType
    24  
    25  		accessToken  string
    26  		refreshToken string
    27  		executeErr   error
    28  		fakeConfig   *uaafakes.FakeConfig
    29  	)
    30  
    31  	BeforeEach(func() {
    32  		fakeConfig = NewTestConfig()
    33  
    34  		client = NewTestUAAClientAndStore(fakeConfig)
    35  	})
    36  
    37  	Describe("Authenticate", func() {
    38  		JustBeforeEach(func() {
    39  			accessToken, refreshToken, executeErr = client.Authenticate(credentials, origin, grantType)
    40  		})
    41  
    42  		When("no errors occur", func() {
    43  			When("the grant type is password", func() {
    44  				var response string
    45  				BeforeEach(func() {
    46  					response = `{
    47  						"access_token":"some-access-token",
    48  						"refresh_token":"some-refresh-token"
    49  					}`
    50  					credentials = map[string]string{
    51  						"username": "some-username",
    52  						"password": "some-password",
    53  					}
    54  					grantType = constant.GrantTypePassword
    55  				})
    56  
    57  				When("origin is not set", func() {
    58  					BeforeEach(func() {
    59  						origin = ""
    60  						server.AppendHandlers(
    61  							CombineHandlers(
    62  								verifyRequestHost(TestAuthorizationResource),
    63  								VerifyRequest(http.MethodPost, "/oauth/token", ""),
    64  								VerifyHeaderKV("Content-Type", "application/x-www-form-urlencoded"),
    65  								VerifyHeaderKV("Authorization", "Basic Y2xpZW50LWlkOmNsaWVudC1zZWNyZXQ="),
    66  								VerifyBody([]byte("grant_type=password&password=some-password&username=some-username")),
    67  								RespondWith(http.StatusOK, response),
    68  							))
    69  					})
    70  
    71  					It("authenticates with the credentials provided", func() {
    72  						Expect(executeErr).NotTo(HaveOccurred())
    73  
    74  						Expect(accessToken).To(Equal("some-access-token"))
    75  						Expect(refreshToken).To(Equal("some-refresh-token"))
    76  					})
    77  				})
    78  
    79  				When("origin is set", func() {
    80  					BeforeEach(func() {
    81  						origin = "some-fake-origin"
    82  						expectedQuery := "login_hint=%7B%22origin%22%3A%22" + origin + "%22%7D"
    83  						server.AppendHandlers(
    84  							CombineHandlers(
    85  								verifyRequestHost(TestAuthorizationResource),
    86  								VerifyRequest(http.MethodPost, "/oauth/token", expectedQuery),
    87  								VerifyHeaderKV("Content-Type", "application/x-www-form-urlencoded"),
    88  								VerifyHeaderKV("Authorization", "Basic Y2xpZW50LWlkOmNsaWVudC1zZWNyZXQ="),
    89  								VerifyBody([]byte("grant_type=password&password=some-password&username=some-username")),
    90  								RespondWith(http.StatusOK, response),
    91  							))
    92  					})
    93  
    94  					It("authenticates with the credentials provided", func() {
    95  						Expect(executeErr).NotTo(HaveOccurred())
    96  
    97  						Expect(accessToken).To(Equal("some-access-token"))
    98  						Expect(refreshToken).To(Equal("some-refresh-token"))
    99  					})
   100  				})
   101  
   102  				When("additional prompts are answered", func() {
   103  					BeforeEach(func() {
   104  						credentials = map[string]string{
   105  							"username":     "some-username",
   106  							"password":     "some-password",
   107  							"mfaCode":      "some-mfa-code",
   108  							"customPrompt": "some-custom-value",
   109  						}
   110  
   111  						expectedValues := url.Values{
   112  							"username":     []string{"some-username"},
   113  							"password":     []string{"some-password"},
   114  							"mfaCode":      []string{"some-mfa-code"},
   115  							"customPrompt": []string{"some-custom-value"},
   116  						}
   117  
   118  						server.AppendHandlers(
   119  							CombineHandlers(
   120  								VerifyForm(expectedValues),
   121  								RespondWith(http.StatusOK, response),
   122  							),
   123  						)
   124  					})
   125  
   126  					It("sends all the prompts to the UAA", func() {
   127  						Expect(executeErr).NotTo(HaveOccurred())
   128  						Expect(accessToken).To(Equal("some-access-token"))
   129  						Expect(refreshToken).To(Equal("some-refresh-token"))
   130  					})
   131  				})
   132  			})
   133  
   134  			When("the grant type is client credentials", func() {
   135  				BeforeEach(func() {
   136  					response := `{
   137  						"access_token":"some-access-token"
   138  					}`
   139  
   140  					credentials = map[string]string{
   141  						"client_id":     "some-client-id",
   142  						"client_secret": "some-client-secret",
   143  					}
   144  					origin = ""
   145  					grantType = constant.GrantTypeClientCredentials
   146  					server.AppendHandlers(
   147  						CombineHandlers(
   148  							verifyRequestHost(TestAuthorizationResource),
   149  							VerifyRequest(http.MethodPost, "/oauth/token"),
   150  							VerifyHeaderKV("Content-Type", "application/x-www-form-urlencoded"),
   151  							VerifyHeaderKV("Authorization"),
   152  							VerifyBody([]byte(fmt.Sprintf("client_id=%s&client_secret=%s&grant_type=%s", credentials["client_id"], credentials["client_secret"], grantType))),
   153  							RespondWith(http.StatusOK, response),
   154  						))
   155  				})
   156  
   157  				It("authenticates with the credentials provided", func() {
   158  					Expect(executeErr).NotTo(HaveOccurred())
   159  
   160  					Expect(accessToken).To(Equal("some-access-token"))
   161  					Expect(refreshToken).To(BeEmpty())
   162  				})
   163  			})
   164  		})
   165  
   166  		When("an error occurs", func() {
   167  			var response string
   168  
   169  			BeforeEach(func() {
   170  				response = `{
   171  						"error": "some-error",
   172  						"error_description": "some-description"
   173  					}`
   174  				server.AppendHandlers(
   175  					CombineHandlers(
   176  						verifyRequestHost(TestAuthorizationResource),
   177  						VerifyRequest(http.MethodPost, "/oauth/token"),
   178  						RespondWith(http.StatusTeapot, response),
   179  					))
   180  			})
   181  
   182  			It("returns the error", func() {
   183  				Expect(executeErr).To(MatchError(RawHTTPStatusError{
   184  					StatusCode:  http.StatusTeapot,
   185  					RawResponse: []byte(response),
   186  				}))
   187  			})
   188  		})
   189  	})
   190  
   191  	Describe("Revoke", func() {
   192  		var (
   193  			jtiFromToken string
   194  			testToken    string
   195  			actualError  error
   196  		)
   197  
   198  		JustBeforeEach(func() {
   199  			actualError = client.Revoke(testToken)
   200  		})
   201  
   202  		When("the call to revoke succeeds", func() {
   203  			BeforeEach(func() {
   204  				testToken = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI1NWZiOTVlM2M5OTY0MmYxODQxMTUyZWIwNmFjYTM4NiIsInJldm9jYWJsZSI6dHJ1ZX0.EYvzQDsCqXRO0r1dowPRYIgeqP_V320v1WbLTG5y6iA"
   205  				jtiFromToken = "55fb95e3c99642f1841152eb06aca386"
   206  				server.AppendHandlers(
   207  					CombineHandlers(
   208  						VerifyRequest(http.MethodDelete, fmt.Sprintf("/oauth/token/revoke/%s", jtiFromToken)),
   209  						VerifyHeaderKV("Authorization: Bearer "+testToken),
   210  						RespondWith(http.StatusOK, nil),
   211  					))
   212  			})
   213  
   214  			It("makes a call to find the jti and uses that jti to revoke the token", func() {
   215  				Expect(actualError).To(BeNil())
   216  				Expect(len(server.ReceivedRequests())).To(Equal(2))
   217  				Expect(server.ReceivedRequests()[1].RequestURI).To(Equal("/oauth/token/revoke/55fb95e3c99642f1841152eb06aca386"))
   218  			})
   219  		})
   220  
   221  		When("the call to revoke the token fails", func() {
   222  			BeforeEach(func() {
   223  				testToken = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI1NWZiOTVlM2M5OTY0MmYxODQxMTUyZWIwNmFjYTM4NiIsInJldm9jYWJsZSI6dHJ1ZX0.EYvzQDsCqXRO0r1dowPRYIgeqP_V320v1WbLTG5y6iA"
   224  				jtiFromToken = "55fb95e3c99642f1841152eb06aca386"
   225  
   226  				server.AppendHandlers(
   227  					CombineHandlers(
   228  						VerifyRequest(http.MethodDelete, fmt.Sprintf("/oauth/token/revoke/%s", jtiFromToken)),
   229  						VerifyHeaderKV("Authorization: Bearer "+testToken),
   230  						RespondWith(http.StatusForbidden, nil),
   231  					))
   232  
   233  			})
   234  			It("returns that failure", func() {
   235  				Expect(actualError).To(MatchError(RawHTTPStatusError{StatusCode: 403, RawResponse: []byte{}}))
   236  			})
   237  		})
   238  
   239  		When("the token contains no jti", func() {
   240  			BeforeEach(func() {
   241  				testToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
   242  			})
   243  			It("returns an error saying it could not parse the jti", func() {
   244  				Expect(actualError).To(Equal(errors.New("could not parse jti from payload")))
   245  			})
   246  		})
   247  	})
   248  })