sentry icon indicating copy to clipboard operation
sentry copied to clipboard

feat(oauth): Add PKCE support for OAuth2 authorization code flow

Open dcramer opened this issue 1 month ago • 2 comments

Implements RFC 7636 Proof Key for Code Exchange (PKCE) to protect OAuth2 authorization code grants from interception attacks. Adds code_challenge and code_challenge_method support to the authorize endpoint, and validates code_verifier in the token endpoint. Supports both S256 and plain methods.

Refs #99002

Replaces #99452

dcramer avatar Dec 04 '25 21:12 dcramer

This PR has a migration; here is the generated SQL for src/sentry/migrations/1012_add_pkce_to_apigrant.py

for 1012_add_pkce_to_apigrant in sentry

--
-- Add field code_challenge to apigrant
--
ALTER TABLE "sentry_apigrant" ADD COLUMN "code_challenge" varchar(128) NULL;
--
-- Add field code_challenge_method to apigrant
--
ALTER TABLE "sentry_apigrant" ADD COLUMN "code_challenge_method" varchar(10) NULL;

github-actions[bot] avatar Dec 04 '25 21:12 github-actions[bot]

:x: 1 Tests Failed:

Tests completed Failed Passed Skipped
30800 1 30799 246
View the top 1 failed test(s) by shortest run time
tests.sentry.web.frontend.test_oauth_token.OAuthTokenCodeTest::test_inactive_application_rejects_token_creation
Stack Traces | 0.395s run time
#x1B[1m#x1B[.../web/frontend/test_oauth_token.py#x1B[0m:334: in test_inactive_application_rejects_token_creation
    assert not ApiGrant.objects.filter(id=self.grant.id).exists()
#x1B[1m#x1B[31mE   assert not True#x1B[0m
#x1B[1m#x1B[31mE    +  where True = <bound method QuerySet.exists of <BaseQuerySet [<ApiGrant at 0x7f28763612e0: id=63>]>>()#x1B[0m
#x1B[1m#x1B[31mE    +    where <bound method QuerySet.exists of <BaseQuerySet [<ApiGrant at 0x7f28763612e0: id=63>]>> = <BaseQuerySet [<ApiGrant at 0x7f2876360ec0: id=63>]>.exists#x1B[0m
#x1B[1m#x1B[31mE    +      where <BaseQuerySet [<ApiGrant at 0x7f2876360ec0: id=63>]> = <bound method QuerySet.filter of <sentry.db.models.manager.base.BaseManager object at 0x7f29627181a0>>(id=63)#x1B[0m
#x1B[1m#x1B[31mE    +        where <bound method QuerySet.filter of <sentry.db.models.manager.base.BaseManager object at 0x7f29627181a0>> = <sentry.db.models.manager.base.BaseManager object at 0x7f29627181a0>.filter#x1B[0m
#x1B[1m#x1B[31mE    +          where <sentry.db.models.manager.base.BaseManager object at 0x7f29627181a0> = ApiGrant.objects#x1B[0m
#x1B[1m#x1B[31mE    +        and   63 = <ApiGrant at 0x7f28763610d0: id=63>.id#x1B[0m
#x1B[1m#x1B[31mE    +          where <ApiGrant at 0x7f28763610d0: id=63> = <sentry.testutils.silo.OAuthTokenCodeTest testMethod=test_inactive_application_rejects_token_creation>.grant#x1B[0m

To view more test analytics, go to the Test Analytics Dashboard 📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

codecov[bot] avatar Dec 04 '25 21:12 codecov[bot]

This PR has a migration; here is the generated SQL for src/sentry/migrations/1013_add_pkce_to_apigrant.py

for 1013_add_pkce_to_apigrant in sentry

--
-- Add field code_challenge to apigrant
--
ALTER TABLE "sentry_apigrant" ADD COLUMN "code_challenge" varchar(128) NULL;
--
-- Add field code_challenge_method to apigrant
--
ALTER TABLE "sentry_apigrant" ADD COLUMN "code_challenge_method" varchar(10) NULL;

github-actions[bot] avatar Dec 09 '25 18:12 github-actions[bot]

This PR has a migration; here is the generated SQL for src/sentry/migrations/1014_add_pkce_to_apigrant.py

for 1014_add_pkce_to_apigrant in sentry

--
-- Add field code_challenge to apigrant
--
ALTER TABLE "sentry_apigrant" ADD COLUMN "code_challenge" varchar(128) NULL;
--
-- Add field code_challenge_method to apigrant
--
ALTER TABLE "sentry_apigrant" ADD COLUMN "code_challenge_method" varchar(10) NULL;

github-actions[bot] avatar Dec 16 '25 20:12 github-actions[bot]

i think we're good to go

dcramer avatar Dec 18 '25 21:12 dcramer