Note on cache semantics (clarification):
- Ensure endpoints use Django's
never_cache for non-cacheable responses. Most of our OAuth views already do (e.g., /oauth/authorize via AuthLoginView and /oauth/token directly). Confirm /oauth/userinfo as well.
- Do not add manual
Cache-Control or Pragma headers in these flows; Pragma is deprecated.
OAuth 2.1 Migration — Plan and Tracking
Summary
Modernize Sentry's OAuth implementation to comply with OAuth 2.1 specifications and security best practices. This includes PKCE enforcement, strict redirect URI validation, refresh token rotation, proper error handling, and discovery endpoints.
Goals
- Align with OAuth 2.1 draft specification
- Improve security through PKCE, strict redirect validation, and token rotation
- Add OAuth 2.0 Authorization Server Metadata discovery (RFC 8414)
Support Dynamic Client Registration (RFC 7591/7592)
- Support CIMD (RFC)
- Maintain backward compatibility during transition
Technical Requirements
OAuth 2.1 Core Requirements
- Remove implicit grant flow (or feature flag to disable)
- Require PKCE for authorization code flow
- Enforce exact redirect URI matching (no prefix matching)
- Implement refresh token rotation with reuse detection
- Support
client_secret_basic authentication method
- Add proper error responses per RFC 6749
Discovery & Metadata (RFC 8414)
/.well-known/oauth-authorization-server endpoint
- Expose supported grant types, response types, and PKCE methods
- Optional OIDC discovery if ID tokens are supported
Security Requirements
- HTTPS enforcement (except loopback for native apps per RFC 8252)
- One-time authorization code usage
- Token family revocation on refresh token reuse
- No credentials in query parameters
- Proper
WWW-Authenticate challenges for Bearer tokens
Implementation Checklist
Phase 1: Core Security Updates
Authorization Endpoint (/oauth/authorize)
Token Endpoint (/oauth/token)
Public Client Support & Refresh Token Rotation
Per RFC 9700 (OAuth 2.0 Security Best Current Practice) §4.14.2:
Discovery Endpoints
Bearer Token Usage (RFC 6750)
Phase 2: Migration & Deprecation
Implicit Flow Removal
Redirect URI Migration
Phase 3: Advanced Features
Dynamic Client Registration
Client ID Metadata Document (CIMD)
Token Management
Sender-Constrained Tokens via DPoP (RFC 9449)
DPoP (Demonstrating Proof of Possession) provides cryptographic sender-constraining for tokens, preventing token theft/replay even if tokens are exfiltrated.
Server-side:
Resource server (API endpoints):
Client requirements (for CLI/SDK implementers):
- Generate asymmetric key pair (ES256 recommended) on first run
- Store private key securely (OS keychain, encrypted file)
- Create signed DPoP proof JWT for each token request
- Include
DPoP: <proof> header in token and API requests
Data Model Changes
ApiGrant
code_challenge: Store PKCE challenge
code_challenge_method: S256 or plain
ApiApplication
client_secret: Make nullable to support public clients (RFC 6749 §2.1)
allow_redirect_prefix_match: Migration flag for redirect behavior
token_endpoint_auth_method: Client authentication method
grant_types: Supported grant types
response_types: Supported response types
require_pkce: PKCE enforcement control
ApiToken
token_family_id: UUID linking tokens in a rotation chain (for replay detection)
previous_refresh_token_hash: Hash of rotated-out refresh token (for replay detection)
is_refresh_token_active: Whether this token's refresh_token can still be used
dpop_jkt: JWK thumbprint of bound DPoP key (for sender-constrained tokens, future)
Rollout Strategy
Feature Flags
oauth2.1:strict-redirects: Enable exact redirect matching
oauth2.1:disable-implicit: Disable implicit flow
oauth2.1:require-pkce: Enforce PKCE
oauth2.1:dynamic-registration: Enable client registration
Migration Path
- Deploy with all flags OFF (backward compatible)
- Enable logging/metrics for deprecated behaviors
- Gradual flag enablement with per-app overrides
- Remove legacy code after full migration
Related Work
References
Success Criteria
- Full OAuth 2.1 compliance
- Zero breaking changes for existing clients during migration
- 100% test coverage for OAuth flows
- Security audit passed
Note on cache semantics (clarification):
never_cachefor non-cacheable responses. Most of our OAuth views already do (e.g.,/oauth/authorizeviaAuthLoginViewand/oauth/tokendirectly). Confirm/oauth/userinfoas well.Cache-ControlorPragmaheaders in these flows;Pragmais deprecated.OAuth 2.1 Migration — Plan and Tracking
Summary
Modernize Sentry's OAuth implementation to comply with OAuth 2.1 specifications and security best practices. This includes PKCE enforcement, strict redirect URI validation, refresh token rotation, proper error handling, and discovery endpoints.
Goals
Support Dynamic Client Registration (RFC 7591/7592)Technical Requirements
OAuth 2.1 Core Requirements
client_secret_basicauthentication methodDiscovery & Metadata (RFC 8414)
/.well-known/oauth-authorization-serverendpointSecurity Requirements
WWW-Authenticatechallenges for Bearer tokensImplementation Checklist
Phase 1: Core Security Updates
Authorization Endpoint (
/oauth/authorize)code_challenge,code_challenge_method) (feat(oauth): Add PKCE support for OAuth2 authorization code flow #104418)ApiGrantmodel (feat(oauth): Add PKCE support for OAuth2 authorization code flow #104418)redirect_uriwhen multiple URIs registered (fix(oauth): Require redirect_uri parameter when multiple URIs are registered #99004)stateparameter in redirectsToken Endpoint (
/oauth/token)client_secret_basicauthentication support (feat(oauth): add client_secret_basic and RFC errors #99148)code_verifieragainst stored challenge (feat(oauth): Add PKCE support for OAuth2 authorization code flow #104418)client_secret) for device flow and PKCE flows (RFC 8628 §5.6)Cache-Control: no-store,Pragma: no-cache) (feat(oauth): add client_secret_basic and RFC errors #99148)WWW-Authenticateheader forinvalid_client(feat(oauth): add client_secret_basic and RFC errors #99148)Public Client Support & Refresh Token Rotation
Per RFC 9700 (OAuth 2.0 Security Best Current Practice) §4.14.2:
is_publicsupport toApiApplication(nullableclient_secret)ApiToken:token_family_id,previous_refresh_token_hash,is_refresh_token_activegrant_type=refresh_tokenwithoutclient_secretDiscovery Endpoints
/.well-known/oauth-authorization-serverBearer Token Usage (RFC 6750)
WWW-Authenticate: Beareron auth errorsPhase 2: Migration & Deprecation
Implicit Flow Removal
oauth2.1:disable-implicitfeature flagunsupported_response_typewhen disabledRedirect URI Migration
oauth2.1:strict-redirectsfeature flagPhase 3: Advanced Features
Dynamic Client RegistrationImplement registration endpoint (RFC 7591)Client management API (RFC 7592)Access control via Initial Access TokensAudit logging for client operationsClient ID Metadata Document (CIMD)
Token Management
Sender-Constrained Tokens via DPoP (RFC 9449)
DPoP (Demonstrating Proof of Possession) provides cryptographic sender-constraining for tokens, preventing token theft/replay even if tokens are exfiltrated.
Server-side:
DPoPheaderjti(unique),htm(HTTP method),htu(URL),iat(timestamp)jtireplay cache (Redis, ~5 min window) to prevent proof reusedpop_jktfield toApiTokento store bound key thumbprintDPoP-Nonceheader for nonce-based replay protection (optional)Resource server (API endpoints):
DPoPauth scheme inAuthorizationheader for DPoP-bound tokensdpop_jktbindingClient requirements (for CLI/SDK implementers):
DPoP: <proof>header in token and API requestsData Model Changes
ApiGrant
code_challenge: Store PKCE challengecode_challenge_method: S256 or plainApiApplication
client_secret: Make nullable to support public clients (RFC 6749 §2.1)allow_redirect_prefix_match: Migration flag for redirect behaviortoken_endpoint_auth_method: Client authentication methodgrant_types: Supported grant typesresponse_types: Supported response typesrequire_pkce: PKCE enforcement controlApiToken
token_family_id: UUID linking tokens in a rotation chain (for replay detection)previous_refresh_token_hash: Hash of rotated-out refresh token (for replay detection)is_refresh_token_active: Whether this token's refresh_token can still be useddpop_jkt: JWK thumbprint of bound DPoP key (for sender-constrained tokens, future)Rollout Strategy
Feature Flags
oauth2.1:strict-redirects: Enable exact redirect matchingoauth2.1:disable-implicit: Disable implicit flowoauth2.1:require-pkce: Enforce PKCEoauth2.1:dynamic-registration: Enable client registrationMigration Path
Related Work
References
Success Criteria