Summary
Implement the Identity Assertion JWT Authorization Grant (ID-JAG) specification to enable enterprise SSO-to-API access.
This allows tools like Cursor to authenticate against Sentry API using existing enterprise IdP tokens (Okta, Azure AD, etc.), enabling seamless developer tooling access via SSO.
Related: RTC-1286 (OAuth 2.1 compliance) - this is a side quest extending that work
Use Case: Cursor + Okta + Sentry
Scenario: Developer at Acme Corp uses Cursor to access Sentry via enterprise SSO.
┌──────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────┐
│ Cursor │ │ Acme Okta │ │ Sentry │ │ Sentry │
└────┬─────┘ └──────┬───────┘ └──────┬───────┘ └────┬────┘
│ 1. OIDC login │ │ │
│─────────────────►│ │ │
│ ◄── ID Token ───│ │ │
│ │ │ │
│ 2. Token Exchange (audience=sentry.io)│ │
│─────────────────►│ │ │
│ ◄── ID-JAG ─────│ │ │
│ │ │ │
│ 3. JWT Bearer Grant (assertion=ID-JAG)│ │
│──────────────────────────────────────►│ │
│ ◄── Access Token (org-scoped) ───────│ │
│ │ │ │
│ 4. API calls ────────────────────────────────────────────►
Flow:
- Developer clicks "Login with SSO" in Cursor → authenticates with Okta
- Cursor exchanges ID token for ID-JAG targeting Sentry
- Cursor presents ID-JAG to Sentry's token endpoint
- Sentry validates, maps user via SSO identity, issues org-scoped token
- Cursor accesses Sentry API
Client Registration Options
How is Cursor registered with Sentry?
The client_id in ID-JAG must match client authentication. Options:
A. Pre-Registered Apps (recommended for MVP)
- Sentry pre-creates entries for known tools (Cursor, VS Code, etc.)
- Enterprises enable in org settings
B. Dynamic Registration (RFC 7591)
- Tools self-register on first use
- More flexible, security concerns
C. IdP-Managed Trust
- No Sentry registration, trust IdP's client_id directly
- IdP controls everything
D. Hybrid Mapping
- Sentry client_id maps to IdP client_ids per issuer
Requirements Checklist
P0 - Critical
P1 - High
P2 - Medium
Technical Details
| Setting |
Value |
Rationale |
| Token Lifetime |
1 day (86400s) |
No refresh tokens per spec |
| Org Scoping |
Required |
Via SSO identity mapping |
| IdP Registration |
Self-service UI |
Similar to current SSO setup |
| Refresh Tokens |
Not issued |
Spec §4.4.3 recommendation |
Files to Modify
Extend Existing:
src/sentry/sentry_apps/token_exchange/util.py - Add RFC 7523 grant type constant
src/sentry/sentry_apps/api/authentication.py - Extend JWT validation for JWKS
src/sentry/web/frontend/oauth_token.py - Add JWT bearer grant handler
src/sentry/utils/jwt.py - Add JWKS fetching/caching
New Files:
src/sentry/models/trustedidentityprovider.py - Trusted IdP model
src/sentry/sentry_apps/token_exchange/idjag_exchanger.py - ID-JAG exchanger (follows GrantExchanger pattern)
Patterns to Follow:
JWTClientSecretAuthentication - existing JWT validation with jti replay prevention
GrantExchanger - token exchange pattern
Spec References
Summary
Implement the Identity Assertion JWT Authorization Grant (ID-JAG) specification to enable enterprise SSO-to-API access.
This allows tools like Cursor to authenticate against Sentry API using existing enterprise IdP tokens (Okta, Azure AD, etc.), enabling seamless developer tooling access via SSO.
Related: RTC-1286 (OAuth 2.1 compliance) - this is a side quest extending that work
Use Case: Cursor + Okta + Sentry
Scenario: Developer at Acme Corp uses Cursor to access Sentry via enterprise SSO.
Flow:
Client Registration Options
How is Cursor registered with Sentry?
The
client_idin ID-JAG must match client authentication. Options:A. Pre-Registered Apps (recommended for MVP)
B. Dynamic Registration (RFC 7591)
C. IdP-Managed Trust
D. Hybrid Mapping
Requirements Checklist
P0 - Critical
urn:ietf:params:oauth:grant-type:jwt-bearer)assertionparameter at/oauth/tokentyp: oauth-id-jag+jwt)iss,sub,aud,client_id,exp,iat,jtiaudmatches Sentry issuerclient_idmatches request authenticationjtitrackingTrustedIdentityProvider)P1 - High
/.well-known/oauth-authorization-server)P2 - Medium
/.well-known/jwks.json)Technical Details
Files to Modify
Extend Existing:
src/sentry/sentry_apps/token_exchange/util.py- Add RFC 7523 grant type constantsrc/sentry/sentry_apps/api/authentication.py- Extend JWT validation for JWKSsrc/sentry/web/frontend/oauth_token.py- Add JWT bearer grant handlersrc/sentry/utils/jwt.py- Add JWKS fetching/cachingNew Files:
src/sentry/models/trustedidentityprovider.py- Trusted IdP modelsrc/sentry/sentry_apps/token_exchange/idjag_exchanger.py- ID-JAG exchanger (followsGrantExchangerpattern)Patterns to Follow:
JWTClientSecretAuthentication- existing JWT validation with jti replay preventionGrantExchanger- token exchange patternSpec References