github.com/DaAlbrecht/cf-cli@v0.0.0-20231128151943-1fe19bb400b9/actor/v7action/auth_test.go (about) 1 package v7action_test 2 3 import ( 4 "errors" 5 6 "code.cloudfoundry.org/cli/actor/actionerror" 7 . "code.cloudfoundry.org/cli/actor/v7action" 8 "code.cloudfoundry.org/cli/actor/v7action/v7actionfakes" 9 "code.cloudfoundry.org/cli/api/uaa/constant" 10 "code.cloudfoundry.org/cli/util/configv3" 11 . "github.com/onsi/ginkgo" 12 . "github.com/onsi/gomega" 13 ) 14 15 var _ = Describe("Default Auth Actions", func() { 16 var ( 17 actor *Actor 18 fakeConfig *v7actionfakes.FakeConfig 19 fakeUAAClient *v7actionfakes.FakeUAAClient 20 creds map[string]string 21 ) 22 23 BeforeEach(func() { 24 fakeConfig = new(v7actionfakes.FakeConfig) 25 fakeUAAClient = new(v7actionfakes.FakeUAAClient) 26 27 fakeConfig.IsCFOnK8sReturns(false) 28 actor = NewActor(nil, fakeConfig, nil, fakeUAAClient, nil, nil) 29 creds = map[string]string{ 30 "client_id": "some-username", 31 "client_secret": "some-password", 32 "origin": "uaa", 33 } 34 }) 35 36 Describe("Authenticate", func() { 37 var ( 38 grantType constant.GrantType 39 actualErr error 40 ) 41 42 JustBeforeEach(func() { 43 actualErr = actor.Authenticate(creds, "uaa", grantType) 44 }) 45 46 When("no API errors occur", func() { 47 BeforeEach(func() { 48 fakeUAAClient.AuthenticateReturns( 49 "some-access-token", 50 "some-refresh-token", 51 nil, 52 ) 53 }) 54 When("nothing is weird", func() { 55 It("works", func() { 56 Expect(fakeUAAClient.AuthenticateCallCount()).To(Equal(1)) 57 }) 58 }) 59 When("the grant type is a password grant", func() { 60 BeforeEach(func() { 61 grantType = constant.GrantTypePassword 62 }) 63 64 It("authenticates the user and returns access and refresh tokens", func() { 65 Expect(actualErr).NotTo(HaveOccurred()) 66 67 Expect(fakeUAAClient.AuthenticateCallCount()).To(Equal(1)) 68 creds, origin, passedGrantType := fakeUAAClient.AuthenticateArgsForCall(0) 69 Expect(creds["client_id"]).To(Equal("some-username")) 70 Expect(creds["client_secret"]).To(Equal("some-password")) 71 Expect(origin).To(Equal("uaa")) 72 Expect(passedGrantType).To(Equal(constant.GrantTypePassword)) 73 74 Expect(fakeConfig.SetTokenInformationCallCount()).To(Equal(1)) 75 accessToken, refreshToken, sshOAuthClient := fakeConfig.SetTokenInformationArgsForCall(0) 76 Expect(accessToken).To(Equal("bearer some-access-token")) 77 Expect(refreshToken).To(Equal("some-refresh-token")) 78 Expect(sshOAuthClient).To(BeEmpty()) 79 80 Expect(fakeConfig.UnsetOrganizationAndSpaceInformationCallCount()).To(Equal(1)) 81 Expect(fakeConfig.SetUAAGrantTypeCallCount()).To(Equal(1)) 82 Expect(fakeConfig.SetUAAGrantTypeArgsForCall(0)).To(Equal("")) 83 }) 84 85 When("a previous user authenticated with a client grant type", func() { 86 BeforeEach(func() { 87 fakeConfig.UAAGrantTypeReturns("client_credentials") 88 }) 89 90 It("returns a PasswordGrantTypeLogoutRequiredError", func() { 91 Expect(actualErr).To(MatchError(actionerror.PasswordGrantTypeLogoutRequiredError{})) 92 Expect(fakeConfig.UAAGrantTypeCallCount()).To(Equal(1)) 93 }) 94 }) 95 }) 96 97 When("the grant type is not password", func() { 98 BeforeEach(func() { 99 grantType = constant.GrantTypeClientCredentials 100 }) 101 102 It("stores the grant type and the client id", func() { 103 Expect(fakeConfig.SetUAAClientCredentialsCallCount()).To(Equal(1)) 104 client, clientSecret := fakeConfig.SetUAAClientCredentialsArgsForCall(0) 105 Expect(client).To(Equal("some-username")) 106 Expect(clientSecret).To(BeEmpty()) 107 Expect(fakeConfig.SetUAAGrantTypeCallCount()).To(Equal(1)) 108 Expect(fakeConfig.SetUAAGrantTypeArgsForCall(0)).To(Equal(string(constant.GrantTypeClientCredentials))) 109 }) 110 }) 111 112 When("extra information is needed to authenticate, e.g., MFA", func() { 113 BeforeEach(func() { 114 creds = map[string]string{ 115 "username": "some-username", 116 "password": "some-password", 117 "mfaCode": "some-one-time-code", 118 } 119 }) 120 121 It("passes the extra information on to the UAA client", func() { 122 uaaCredentials, _, _ := fakeUAAClient.AuthenticateArgsForCall(0) 123 Expect(uaaCredentials).To(BeEquivalentTo(map[string]string{ 124 "username": "some-username", 125 "password": "some-password", 126 "mfaCode": "some-one-time-code", 127 })) 128 }) 129 }) 130 }) 131 132 When("an API error occurs", func() { 133 var expectedErr error 134 135 BeforeEach(func() { 136 expectedErr = errors.New("some error") 137 fakeUAAClient.AuthenticateReturns( 138 "", 139 "", 140 expectedErr, 141 ) 142 }) 143 144 It("returns the error", func() { 145 Expect(actualErr).To(MatchError(expectedErr)) 146 147 Expect(fakeConfig.SetTokenInformationCallCount()).To(Equal(1)) 148 accessToken, refreshToken, sshOAuthClient := fakeConfig.SetTokenInformationArgsForCall(0) 149 Expect(accessToken).To(BeEmpty()) 150 Expect(refreshToken).To(BeEmpty()) 151 Expect(sshOAuthClient).To(BeEmpty()) 152 153 Expect(fakeConfig.UnsetOrganizationAndSpaceInformationCallCount()).To(Equal(1)) 154 }) 155 }) 156 }) 157 158 Describe("RevokeAccessAndRefreshTokens", func() { 159 var ( 160 expectedAccessToken string 161 expectedRefreshToken string 162 ) 163 164 BeforeEach(func() { 165 expectedAccessToken = "eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vdWFhLmdlb2RlLWJhbmUubGl0ZS5jbGkuZnVuL3Rva2VuX2tleXMiLCJraWQiOiJrZXktMSIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIzN2IyZjA0NmIyMGY0MjY1OGY1MWYzZGY4NDZhNjFhOSIsInN1YiI6IjExMjc0OTU2LTYyNTUtNDAyNi05MjUzLWM4ZjE0OWMxZDBkOCIsInNjb3BlIjpbImNsb3VkX2NvbnRyb2xsZXIuYWRtaW4iLCJyb3V0aW5nLnJvdXRlcl9ncm91cHMucmVhZCIsImNsb3VkX2NvbnRyb2xsZXIud3JpdGUiLCJuZXR3b3JrLmFkbWluIiwiZG9wcGxlci5maXJlaG9zZSIsImNsaWVudHMucmVhZCIsInVhYS5yZXNvdXJjZSIsIm9wZW5pZCIsInJvdXRpbmcucm91dGVyX2dyb3Vwcy53cml0ZSIsInNjaW0ucmVhZCIsInVhYS51c2VyIiwiY2xvdWRfY29udHJvbGxlci5yZWFkIiwicGFzc3dvcmQud3JpdGUiLCJzY2ltLndyaXRlIl0sImNsaWVudF9pZCI6ImNmIiwiY2lkIjoiY2YiLCJhenAiOiJjZiIsInJldm9jYWJsZSI6dHJ1ZSwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwidXNlcl9pZCI6IjExMjc0OTU2LTYyNTUtNDAyNi05MjUzLWM4ZjE0OWMxZDBkOCIsIm9yaWdpbiI6InVhYSIsInVzZXJfbmFtZSI6ImFkbWluIiwiZW1haWwiOiJhZG1pbiIsImF1dGhfdGltZSI6MTU5NjY2Nzk0NywicmV2X3NpZyI6ImNlNzJmN2IzIiwiaWF0IjoxNTk2NjY3OTQ3LCJleHAiOjE1OTY2Njg1NDcsImlzcyI6Imh0dHBzOi8vdWFhLmdlb2RlLWJhbmUubGl0ZS5jbGkuZnVuL29hdXRoL3Rva2VuIiwiemlkIjoidWFhIiwiYXVkIjpbImNsb3VkX2NvbnRyb2xsZXIiLCJzY2ltIiwicGFzc3dvcmQiLCJjZiIsImNsaWVudHMiLCJ1YWEiLCJvcGVuaWQiLCJkb3BwbGVyIiwicm91dGluZy5yb3V0ZXJfZ3JvdXBzIiwibmV0d29yayJdfQ.WGRIexU6aheL6VOxK3lOCdQzv8GNK_O1IHu77pyEl0Y5wxa10T1H0VppzpKPbxYJ1C9QvQp1UwTk8fU9ylJ6lFAhA1xXLpBHNMI66QSVYc2m2TmOMUbJjWoE3w7cF-cBM1Unle3JlRk7y8yK4jeo0Gwj1fWcE4JNDKypTrT7yd5WxRCcMk1pWTJtLH9Rgng0Ei6i15NJ9K2SbF-rQWQp0qr1l4PBcyrjf7hWbf365yZFUSDMtPAToiJeKT3qmmN37elDmvFYzFNN4MEqEoirWYfjjakulLh9TPWELiygwNzDi11MYO07ksCUow9ArcA7cSlpnh9qrfPOqlfZTizBGg" 166 expectedRefreshToken = "eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vdWFhLmdlb2RlLWJhbmUubGl0ZS5jbGkuZnVuL3Rva2VuX2tleXMiLCJraWQiOiJrZXktMSIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIzN2IyZjA0NmIyMGY0MjY1OGY1MWYzZGY4NDZhNjFhOSIsInN1YiI6IjExMjc0OTU2LTYyNTUtNDAyNi05MjUzLWM4ZjE0OWMxZDBkOCIsInNjb3BlIjpbImNsb3VkX2NvbnRyb2xsZXIuYWRtaW4iLCJyb3V0aW5nLnJvdXRlcl9ncm91cHMucmVhZCIsImNsb3VkX2NvbnRyb2xsZXIud3JpdGUiLCJuZXR3b3JrLmFkbWluIiwiZG9wcGxlci5maXJlaG9zZSIsImNsaWVudHMucmVhZCIsInVhYS5yZXNvdXJjZSIsIm9wZW5pZCIsInJvdXRpbmcucm91dGVyX2dyb3Vwcy53cml0ZSIsInNjaW0ucmVhZCIsInVhYS51c2VyIiwiY2xvdWRfY29udHJvbGxlci5yZWFkIiwicGFzc3dvcmQud3JpdGUiLCJzY2ltLndyaXRlIl0sImNsaWVudF9pZCI6ImNmIiwiY2lkIjoiY2YiLCJhenAiOiJjZiIsInJldm9jYWJsZSI6dHJ1ZSwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwidXNlcl9pZCI6IjExMjc0OTU2LTYyNTUtNDAyNi05MjUzLWM4ZjE0OWMxZDBkOCIsIm9yaWdpbiI6InVhYSIsInVzZXJfbmFtZSI6ImFkbWluIiwiZW1haWwiOiJhZG1pbiIsImF1dGhfdGltZSI6MTU5NjY2Nzk0NywicmV2X3NpZyI6ImNlNzJmN2IzIiwiaWF0IjoxNTk2NjY3OTQ3LCJleHAiOjE1OTY2Njg1NDcsImlzcyI6Imh0dHBzOi8vdWFhLmdlb2RlLWJhbmUubGl0ZS5jbGkuZnVuL29hdXRoL3Rva2VuIiwiemlkIjoidWFhIiwiYXVkIjpbImNsb3VkX2NvbnRyb2xsZXIiLCJzY2ltIiwicGFzc3dvcmQiLCJjZiIsImNsaWVudHMiLCJ1YWEiLCJvcGVuaWQiLCJkb3BwbGVyIiwicm91dGluZy5yb3V0ZXJfZ3JvdXBzIiwibmV0d29yayJdfQ.WGRIexU6aheL6VOxK3lOCdQzv8GNK_O1IHu77pyEl0Y5wxa10T1H0VppzpKPbxYJ1C9QvQp1UwTk8fU9ylJ6lFAhA1xXLpBHNMI66QSVYc2m2TmOMUbJjWoE3w7cF-cBM1Unle3JlRk7y8yK4jeo0Gwj1fWcE4JNDKypTrT7yd5WxRCcMk1pWTJtLH9Rgng0Ei6i15NJ9K2SbF-rQWQp0qr1l4PBcyrjf7hWbf365yZFUSDMtPAToiJeKT3qmmN37elDmvFYzFNN4MEqEoirWYfjjakulLh9TPWELiygwNzDi11MYO07ksCUow9ArcA7cSlpnh9qrfPOqlfZTizBGg" 167 fakeConfig.AccessTokenReturns(expectedAccessToken) 168 fakeConfig.RefreshTokenReturns(expectedRefreshToken) 169 }) 170 171 JustBeforeEach(func() { 172 _ = actor.RevokeAccessAndRefreshTokens() 173 }) 174 175 When("the token is revokable", func() { 176 It("calls the UAA to revoke refresh and access tokens", func() { 177 Expect(fakeUAAClient.RevokeCallCount()).To(Equal(2)) 178 179 Expect(fakeUAAClient.RevokeArgsForCall(0)).To(Equal(expectedRefreshToken)) 180 Expect(fakeUAAClient.RevokeArgsForCall(1)).To(Equal(expectedAccessToken)) 181 }) 182 }) 183 184 When("the token is not revokable", func() { 185 BeforeEach(func() { 186 expectedAccessToken = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMTI3NDk1Ni02MjU1LTQwMjYtOTI1My1jOGYxNDljMWQwZDgiLCJhdWQiOltdfQ.rVlUqVTglhod_MEbdnczGwj4IJIMHqiLrqaX2wvEWMw" 187 fakeConfig.AccessTokenReturns(expectedAccessToken) 188 }) 189 190 It("does not call the UAA to revoke refresh and access tokens", func() { 191 Expect(fakeUAAClient.RevokeCallCount()).To(Equal(0)) 192 }) 193 }) 194 }) 195 196 Describe("Get Current User", func() { 197 var ( 198 user configv3.User 199 err error 200 ) 201 202 JustBeforeEach(func() { 203 user, err = actor.GetCurrentUser() 204 }) 205 206 BeforeEach(func() { 207 fakeConfig.CurrentUserReturns(configv3.User{Name: "jim"}, nil) 208 }) 209 210 It("delegates to the injected config", func() { 211 Expect(err).NotTo(HaveOccurred()) 212 Expect(user.Name).To(Equal("jim")) 213 }) 214 }) 215 })