github.com/mattermost/mattermost-server/v5@v5.39.3/store/storetest/oauth_store.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package storetest 5 6 import ( 7 "context" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 13 "github.com/mattermost/mattermost-server/v5/model" 14 "github.com/mattermost/mattermost-server/v5/store" 15 ) 16 17 func TestOAuthStore(t *testing.T, ss store.Store) { 18 t.Run("SaveApp", func(t *testing.T) { testOAuthStoreSaveApp(t, ss) }) 19 t.Run("GetApp", func(t *testing.T) { testOAuthStoreGetApp(t, ss) }) 20 t.Run("UpdateApp", func(t *testing.T) { testOAuthStoreUpdateApp(t, ss) }) 21 t.Run("SaveAccessData", func(t *testing.T) { testOAuthStoreSaveAccessData(t, ss) }) 22 t.Run("OAuthUpdateAccessData", func(t *testing.T) { testOAuthUpdateAccessData(t, ss) }) 23 t.Run("GetAccessData", func(t *testing.T) { testOAuthStoreGetAccessData(t, ss) }) 24 t.Run("RemoveAccessData", func(t *testing.T) { testOAuthStoreRemoveAccessData(t, ss) }) 25 t.Run("RemoveAllAccessData", func(t *testing.T) { testOAuthStoreRemoveAllAccessData(t, ss) }) 26 t.Run("SaveAuthData", func(t *testing.T) { testOAuthStoreSaveAuthData(t, ss) }) 27 t.Run("GetAuthData", func(t *testing.T) { testOAuthStoreGetAuthData(t, ss) }) 28 t.Run("RemoveAuthData", func(t *testing.T) { testOAuthStoreRemoveAuthData(t, ss) }) 29 t.Run("RemoveAuthDataByUser", func(t *testing.T) { testOAuthStoreRemoveAuthDataByUser(t, ss) }) 30 t.Run("OAuthGetAuthorizedApps", func(t *testing.T) { testOAuthGetAuthorizedApps(t, ss) }) 31 t.Run("OAuthGetAccessDataByUserForApp", func(t *testing.T) { testOAuthGetAccessDataByUserForApp(t, ss) }) 32 t.Run("DeleteApp", func(t *testing.T) { testOAuthStoreDeleteApp(t, ss) }) 33 } 34 35 func testOAuthStoreSaveApp(t *testing.T, ss store.Store) { 36 a1 := model.OAuthApp{} 37 a1.CreatorId = model.NewId() 38 a1.CallbackUrls = []string{"https://nowhere.com"} 39 a1.Homepage = "https://nowhere.com" 40 41 // Try to save an app that already has an Id 42 a1.Id = model.NewId() 43 _, err := ss.OAuth().SaveApp(&a1) 44 require.Error(t, err, "Should have failed, cannot add an OAuth app cannot be save with an Id, it has to be updated") 45 46 // Try to save an Invalid App 47 a1.Id = "" 48 _, err = ss.OAuth().SaveApp(&a1) 49 require.Error(t, err, "Should have failed, app should be invalid cause it doesn' have a name set") 50 51 // Save the app 52 a1.Id = "" 53 a1.Name = "TestApp" + model.NewId() 54 _, err = ss.OAuth().SaveApp(&a1) 55 require.NoError(t, err) 56 } 57 58 func testOAuthStoreGetApp(t *testing.T, ss store.Store) { 59 a1 := model.OAuthApp{} 60 a1.CreatorId = model.NewId() 61 a1.Name = "TestApp" + model.NewId() 62 a1.CallbackUrls = []string{"https://nowhere.com"} 63 a1.Homepage = "https://nowhere.com" 64 _, err := ss.OAuth().SaveApp(&a1) 65 require.NoError(t, err) 66 67 // Lets try to get and app that does not exists 68 _, err = ss.OAuth().GetApp("fake0123456789abcderfgret1") 69 require.Error(t, err, "Should have failed. App does not exists") 70 71 _, err = ss.OAuth().GetApp(a1.Id) 72 require.NoError(t, err) 73 74 // Lets try and get the app from a user that hasn't created any apps 75 apps, err := ss.OAuth().GetAppByUser("fake0123456789abcderfgret1", 0, 1000) 76 require.NoError(t, err) 77 assert.Empty(t, apps, "Should have failed. Fake user hasn't created any apps") 78 79 _, err = ss.OAuth().GetAppByUser(a1.CreatorId, 0, 1000) 80 require.NoError(t, err) 81 82 _, err = ss.OAuth().GetApps(0, 1000) 83 require.NoError(t, err) 84 } 85 86 func testOAuthStoreUpdateApp(t *testing.T, ss store.Store) { 87 a1 := model.OAuthApp{} 88 a1.CreatorId = model.NewId() 89 a1.Name = "TestApp" + model.NewId() 90 a1.CallbackUrls = []string{"https://nowhere.com"} 91 a1.Homepage = "https://nowhere.com" 92 _, err := ss.OAuth().SaveApp(&a1) 93 require.NoError(t, err) 94 95 // temporarily save the created app id 96 id := a1.Id 97 98 a1.CreateAt = 1 99 a1.ClientSecret = "pwd" 100 a1.CreatorId = "12345678901234567890123456" 101 102 // Lets update the app by removing the name 103 a1.Name = "" 104 _, err = ss.OAuth().UpdateApp(&a1) 105 require.Error(t, err, "Should have failed. App name is not set") 106 107 // Lets not find the app that we are trying to update 108 a1.Id = "fake0123456789abcderfgret1" 109 a1.Name = "NewName" 110 _, err = ss.OAuth().UpdateApp(&a1) 111 require.Error(t, err, "Should have failed. Not able to find the app") 112 113 a1.Id = id 114 ua, err := ss.OAuth().UpdateApp(&a1) 115 require.NoError(t, err) 116 require.Equal(t, ua.Name, "NewName", "name did not update") 117 require.NotEqual(t, ua.CreateAt, 1, "create at should not have updated") 118 require.NotEqual(t, ua.CreatorId, "12345678901234567890123456", "creator id should not have updated") 119 } 120 121 func testOAuthStoreSaveAccessData(t *testing.T, ss store.Store) { 122 a1 := model.AccessData{} 123 a1.ClientId = model.NewId() 124 a1.UserId = model.NewId() 125 126 // Lets try and save an incomplete access data 127 _, err := ss.OAuth().SaveAccessData(&a1) 128 require.Error(t, err, "Should have failed. Access data needs the token") 129 130 a1.Token = model.NewId() 131 a1.RefreshToken = model.NewId() 132 a1.RedirectUri = "http://example.com" 133 134 _, err = ss.OAuth().SaveAccessData(&a1) 135 require.NoError(t, err) 136 } 137 138 func testOAuthUpdateAccessData(t *testing.T, ss store.Store) { 139 a1 := model.AccessData{} 140 a1.ClientId = model.NewId() 141 a1.UserId = model.NewId() 142 a1.Token = model.NewId() 143 a1.RefreshToken = model.NewId() 144 a1.ExpiresAt = model.GetMillis() 145 a1.RedirectUri = "http://example.com" 146 _, err := ss.OAuth().SaveAccessData(&a1) 147 require.NoError(t, err) 148 149 //Try to update to invalid Refresh Token 150 refreshToken := a1.RefreshToken 151 a1.RefreshToken = model.NewId() + "123" 152 _, err = ss.OAuth().UpdateAccessData(&a1) 153 require.Error(t, err, "Should have failed with invalid token") 154 155 //Try to update to invalid RedirectUri 156 a1.RefreshToken = model.NewId() 157 a1.RedirectUri = "" 158 _, err = ss.OAuth().UpdateAccessData(&a1) 159 require.Error(t, err, "Should have failed with invalid Redirect URI") 160 161 // Should update fine 162 a1.RedirectUri = "http://example.com" 163 ra1, err := ss.OAuth().UpdateAccessData(&a1) 164 require.NoError(t, err) 165 require.NotEqual(t, ra1.RefreshToken, refreshToken, "refresh tokens didn't match") 166 } 167 168 func testOAuthStoreGetAccessData(t *testing.T, ss store.Store) { 169 a1 := model.AccessData{} 170 a1.ClientId = model.NewId() 171 a1.UserId = model.NewId() 172 a1.Token = model.NewId() 173 a1.RefreshToken = model.NewId() 174 a1.ExpiresAt = model.GetMillis() 175 a1.RedirectUri = "http://example.com" 176 _, err := ss.OAuth().SaveAccessData(&a1) 177 require.NoError(t, err) 178 179 _, err = ss.OAuth().GetAccessData("invalidToken") 180 require.Error(t, err, "Should have failed. There is no data with an invalid token") 181 182 ra1, err := ss.OAuth().GetAccessData(a1.Token) 183 require.NoError(t, err) 184 assert.Equal(t, a1.Token, ra1.Token, "tokens didn't match") 185 186 _, err = ss.OAuth().GetPreviousAccessData(a1.UserId, a1.ClientId) 187 require.NoError(t, err) 188 189 _, err = ss.OAuth().GetPreviousAccessData("user", "junk") 190 require.NoError(t, err) 191 192 // Try to get the Access data using an invalid refresh token 193 _, err = ss.OAuth().GetAccessDataByRefreshToken(a1.Token) 194 require.Error(t, err, "Should have failed. There is no data with an invalid token") 195 196 // Get the Access Data using the refresh token 197 ra1, err = ss.OAuth().GetAccessDataByRefreshToken(a1.RefreshToken) 198 require.NoError(t, err) 199 assert.Equal(t, a1.RefreshToken, ra1.RefreshToken, "tokens didn't match") 200 } 201 202 func testOAuthStoreRemoveAccessData(t *testing.T, ss store.Store) { 203 a1 := model.AccessData{} 204 a1.ClientId = model.NewId() 205 a1.UserId = model.NewId() 206 a1.Token = model.NewId() 207 a1.RefreshToken = model.NewId() 208 a1.RedirectUri = "http://example.com" 209 _, err := ss.OAuth().SaveAccessData(&a1) 210 require.NoError(t, err) 211 212 err = ss.OAuth().RemoveAccessData(a1.Token) 213 require.NoError(t, err) 214 215 result, _ := ss.OAuth().GetPreviousAccessData(a1.UserId, a1.ClientId) 216 require.Nil(t, result, "did not delete access token") 217 } 218 219 func testOAuthStoreRemoveAllAccessData(t *testing.T, ss store.Store) { 220 a1 := model.AccessData{} 221 a1.ClientId = model.NewId() 222 a1.UserId = model.NewId() 223 a1.Token = model.NewId() 224 a1.RefreshToken = model.NewId() 225 a1.RedirectUri = "http://example.com" 226 _, err := ss.OAuth().SaveAccessData(&a1) 227 require.NoError(t, err) 228 229 err = ss.OAuth().RemoveAllAccessData() 230 require.NoError(t, err) 231 232 result, _ := ss.OAuth().GetPreviousAccessData(a1.UserId, a1.ClientId) 233 require.Nil(t, result, "did not delete access token") 234 } 235 236 func testOAuthStoreSaveAuthData(t *testing.T, ss store.Store) { 237 a1 := model.AuthData{} 238 a1.ClientId = model.NewId() 239 a1.UserId = model.NewId() 240 a1.Code = model.NewId() 241 a1.RedirectUri = "http://example.com" 242 _, err := ss.OAuth().SaveAuthData(&a1) 243 require.NoError(t, err) 244 } 245 246 func testOAuthStoreGetAuthData(t *testing.T, ss store.Store) { 247 a1 := model.AuthData{} 248 a1.ClientId = model.NewId() 249 a1.UserId = model.NewId() 250 a1.Code = model.NewId() 251 a1.RedirectUri = "http://example.com" 252 _, err := ss.OAuth().SaveAuthData(&a1) 253 require.NoError(t, err) 254 255 _, err = ss.OAuth().GetAuthData(a1.Code) 256 require.NoError(t, err) 257 } 258 259 func testOAuthStoreRemoveAuthData(t *testing.T, ss store.Store) { 260 a1 := model.AuthData{} 261 a1.ClientId = model.NewId() 262 a1.UserId = model.NewId() 263 a1.Code = model.NewId() 264 a1.RedirectUri = "http://example.com" 265 _, err := ss.OAuth().SaveAuthData(&a1) 266 require.NoError(t, err) 267 268 err = ss.OAuth().RemoveAuthData(a1.Code) 269 require.NoError(t, err) 270 271 _, err = ss.OAuth().GetAuthData(a1.Code) 272 require.Error(t, err, "should have errored - auth code removed") 273 } 274 275 func testOAuthStoreRemoveAuthDataByUser(t *testing.T, ss store.Store) { 276 a1 := model.AuthData{} 277 a1.ClientId = model.NewId() 278 a1.UserId = model.NewId() 279 a1.Code = model.NewId() 280 a1.RedirectUri = "http://example.com" 281 _, err := ss.OAuth().SaveAuthData(&a1) 282 require.NoError(t, err) 283 284 err = ss.OAuth().PermanentDeleteAuthDataByUser(a1.UserId) 285 require.NoError(t, err) 286 } 287 288 func testOAuthGetAuthorizedApps(t *testing.T, ss store.Store) { 289 a1 := model.OAuthApp{} 290 a1.CreatorId = model.NewId() 291 a1.Name = "TestApp" + model.NewId() 292 a1.CallbackUrls = []string{"https://nowhere.com"} 293 a1.Homepage = "https://nowhere.com" 294 _, err := ss.OAuth().SaveApp(&a1) 295 require.NoError(t, err) 296 297 // Lets try and get an Authorized app for a user who hasn't authorized it 298 apps, err := ss.OAuth().GetAuthorizedApps("fake0123456789abcderfgret1", 0, 1000) 299 require.NoError(t, err) 300 assert.Empty(t, apps, "Should have failed. Fake user hasn't authorized the app") 301 302 // allow the app 303 p := model.Preference{} 304 p.UserId = a1.CreatorId 305 p.Category = model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP 306 p.Name = a1.Id 307 p.Value = "true" 308 nErr := ss.Preference().Save(&model.Preferences{p}) 309 require.NoError(t, nErr) 310 311 apps, err = ss.OAuth().GetAuthorizedApps(a1.CreatorId, 0, 1000) 312 require.NoError(t, err) 313 assert.NotEqual(t, len(apps), 0, "It should have return apps") 314 } 315 316 func testOAuthGetAccessDataByUserForApp(t *testing.T, ss store.Store) { 317 a1 := model.OAuthApp{} 318 a1.CreatorId = model.NewId() 319 a1.Name = "TestApp" + model.NewId() 320 a1.CallbackUrls = []string{"https://nowhere.com"} 321 a1.Homepage = "https://nowhere.com" 322 _, err := ss.OAuth().SaveApp(&a1) 323 require.NoError(t, err) 324 325 // allow the app 326 p := model.Preference{} 327 p.UserId = a1.CreatorId 328 p.Category = model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP 329 p.Name = a1.Id 330 p.Value = "true" 331 nErr := ss.Preference().Save(&model.Preferences{p}) 332 require.NoError(t, nErr) 333 334 apps, err := ss.OAuth().GetAuthorizedApps(a1.CreatorId, 0, 1000) 335 require.NoError(t, err) 336 assert.NotEqual(t, len(apps), 0, "It should have return apps") 337 338 // save the token 339 ad1 := model.AccessData{} 340 ad1.ClientId = a1.Id 341 ad1.UserId = a1.CreatorId 342 ad1.Token = model.NewId() 343 ad1.RefreshToken = model.NewId() 344 ad1.RedirectUri = "http://example.com" 345 346 _, err = ss.OAuth().SaveAccessData(&ad1) 347 require.NoError(t, err) 348 349 accessData, err := ss.OAuth().GetAccessDataByUserForApp(a1.CreatorId, a1.Id) 350 require.NoError(t, err) 351 assert.NotEqual(t, len(accessData), 0, "It should have return access data") 352 } 353 354 func testOAuthStoreDeleteApp(t *testing.T, ss store.Store) { 355 a1 := model.OAuthApp{} 356 a1.CreatorId = model.NewId() 357 a1.Name = "TestApp" + model.NewId() 358 a1.CallbackUrls = []string{"https://nowhere.com"} 359 a1.Homepage = "https://nowhere.com" 360 _, err := ss.OAuth().SaveApp(&a1) 361 require.NoError(t, err) 362 363 // delete a non-existent app 364 err = ss.OAuth().DeleteApp("fakeclientId") 365 require.NoError(t, err) 366 367 s1 := &model.Session{} 368 s1.UserId = model.NewId() 369 s1.Token = model.NewId() 370 s1.IsOAuth = true 371 372 s1, nErr := ss.Session().Save(s1) 373 require.NoError(t, nErr) 374 375 ad1 := model.AccessData{} 376 ad1.ClientId = a1.Id 377 ad1.UserId = a1.CreatorId 378 ad1.Token = s1.Token 379 ad1.RefreshToken = model.NewId() 380 ad1.RedirectUri = "http://example.com" 381 382 _, err = ss.OAuth().SaveAccessData(&ad1) 383 require.NoError(t, err) 384 385 err = ss.OAuth().DeleteApp(a1.Id) 386 require.NoError(t, err) 387 388 _, nErr = ss.Session().Get(context.Background(), s1.Token) 389 require.Error(t, nErr, "should error - session should be deleted") 390 391 _, err = ss.OAuth().GetAccessData(s1.Token) 392 require.Error(t, err, "should error - access data should be deleted") 393 }