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  })