@@ -229,6 +229,49 @@ def test_token_hashed_with_option_off(self):
229229 assert api_token .hashed_token == expected_hash
230230
231231
232+ @no_silo_test
233+ class TestTokenAuthenticationReplication (TestCase ):
234+ def setUp (self ):
235+ super ().setUp ()
236+
237+ self .auth = UserAuthTokenAuthentication ()
238+
239+ @override_options ({"apitoken.save-hash-on-create" : False })
240+ def test_hash_is_replicated (self ):
241+ api_token = ApiToken .objects .create (user = self .user , token_type = AuthTokenType .USER )
242+ expected_hash = hashlib .sha256 (api_token .token .encode ()).hexdigest ()
243+
244+ # we haven't authenticated to the API endpoint yet, so this value should be empty
245+ assert api_token .hashed_token is None
246+
247+ request = HttpRequest ()
248+ request .META ["HTTP_AUTHORIZATION" ] = f"Bearer { api_token .token } "
249+
250+ with assume_test_silo_mode (SiloMode .REGION ):
251+ with outbox_runner ():
252+ # make sure the token was replicated
253+ api_token_replica = ApiTokenReplica .objects .get (apitoken_id = api_token .id )
254+ assert api_token .token == api_token_replica .token
255+ assert (
256+ api_token_replica .hashed_token is None
257+ ) # we don't expect to have a hashed value yet
258+
259+ # trigger the authentication middleware, and thus the hashing backfill
260+ result = self .auth .authenticate (request )
261+ assert result is not None
262+
263+ # check for the expected hash value
264+ api_token .refresh_from_db ()
265+ assert api_token .hashed_token == expected_hash
266+
267+ # ApiTokenReplica should also be updated
268+ api_token_replica .refresh_from_db ()
269+ assert api_token_replica .hashed_token == expected_hash
270+
271+ # just for good measure
272+ assert api_token .hashed_token == api_token_replica .hashed_token
273+
274+
232275@django_db_all
233276@pytest .mark .parametrize ("internal" , [True , False ])
234277def test_registered_relay (internal ):
@@ -396,44 +439,6 @@ def test_api_tokens(self):
396439 assert auth_token .scopes == token .get_scopes ()
397440 assert auth_token .audit_log_data == token .get_audit_log_data ()
398441
399- @override_options ({"apitoken.save-hash-on-create" : False })
400- def test_user_auth_token_hashed_with_option_off (self ):
401- # see https://github.com/getsentry/sentry/pull/65941
402- # the UserAuthTokenAuthentication middleware was updated to hash tokens as
403- # they were used, this test verifies the hash
404- api_token = ApiToken .objects .create (user = self .user , token_type = AuthTokenType .USER )
405- expected_hash = hashlib .sha256 (api_token .token .encode ()).hexdigest ()
406-
407- # we haven't authenticated to the API endpoint yet, so this value should be empty
408- assert api_token .hashed_token is None
409-
410- request = HttpRequest ()
411- request .META ["HTTP_AUTHORIZATION" ] = f"Bearer { api_token .token } "
412-
413- with outbox_runner ():
414- with assume_test_silo_mode (SiloMode .REGION ):
415- # make sure the token was replicated
416- api_token_replica = ApiTokenReplica .objects .get (apitoken_id = api_token .id )
417- assert api_token .token == api_token_replica .token
418- assert (
419- api_token_replica .hashed_token is None
420- ) # we don't expect to have a hashed value yet
421-
422- # trigger the authentication middleware, and thus the hashing backfill
423- result = self .auth .authenticate (request )
424- assert result is not None
425-
426- # check for the expected hash value
427- api_token .refresh_from_db ()
428- assert api_token .hashed_token == expected_hash
429-
430- # ApiTokenReplica should also be updated
431- api_token_replica .refresh_from_db ()
432- assert api_token_replica .hashed_token == expected_hash
433-
434- # just for good measure
435- assert api_token .hashed_token == api_token_replica .hashed_token
436-
437442 def test_api_keys (self ):
438443 ak = self .create_api_key (organization = self .organization , scope_list = ["projects:read" ])
439444 with assume_test_silo_mode (SiloMode .REGION ):
0 commit comments