Skip to content

Commit 51e64ce

Browse files
committed
fix: use lock in grant exchanger
1 parent 10b51c6 commit 51e64ce

File tree

1 file changed

+16
-5
lines changed

1 file changed

+16
-5
lines changed

src/sentry/sentry_apps/token_exchange/grant_exchanger.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from django.utils.functional import cached_property
77

88
from sentry import analytics
9+
from sentry.locks import locks
910
from sentry.models.apiapplication import ApiApplication
1011
from sentry.models.apigrant import ApiGrant
1112
from sentry.models.apitoken import ApiToken
@@ -35,12 +36,22 @@ class GrantExchanger:
3536
def run(self):
3637
with transaction.atomic(using=router.db_for_write(ApiToken)):
3738
try:
38-
self._validate()
39-
token = self._create_token()
39+
lock = locks.get(
40+
ApiGrant.get_lock_key(self.grant.id),
41+
duration=10,
42+
name="api_grant",
43+
)
44+
45+
# we use a lock to prevent race conditions when creating the ApiToken
46+
# an attacker could send two requests to create an access/refresh token pair
47+
# at the same time, using the same grant, and get two different tokens
48+
with lock.acquire():
49+
self._validate()
50+
token = self._create_token()
4051

41-
# Once it's exchanged it's no longer valid and should not be
42-
# exchangeable, so we delete it.
43-
self._delete_grant()
52+
# Once it's exchanged it's no longer valid and should not be
53+
# exchangeable, so we delete it.
54+
self._delete_grant()
4455
except SentryAppIntegratorError:
4556
logger.info(
4657
"grant-exchanger.context",

0 commit comments

Comments
 (0)