github.com/wanddynosios/cli/v8@v8.7.9-0.20240221182337-1a92e3a7017f/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(1)) 217 Expect(server.ReceivedRequests()[0].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 })