-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Description
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: #99002 (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
-
JWT Bearer Grant (
urn:ietf:params:oauth:grant-type:jwt-bearer)- Accept
assertionparameter at/oauth/token - Validate JWT header (
typ: oauth-id-jag+jwt) - Validate signature via IdP JWKS
- Validate required claims:
iss,sub,aud,client_id,exp,iat,jti - Map subject to Sentry user via SSO identity
- Accept
-
ID-JAG Validation
- Verify
audmatches Sentry issuer - Verify
client_idmatches request authentication - Implement replay prevention via
jtitracking - Scope intersection (ID-JAG × request × client × user)
- Verify
-
Trusted IdP Configuration
- Model for trusted IdP registration (
TrustedIdentityProvider) - JWKS fetching with caching
- Subject-to-user mapping via AuthIdentity
- Model for trusted IdP registration (
-
Security
- Confidential clients only
- Audit logging
- No refresh tokens (per spec §4.4.3)
P1 - High
-
OAuth Metadata (
/.well-known/oauth-authorization-server)- Advertise supported grant types
- Document PKCE, scopes, auth methods
-
Self-Service IdP Management UI
- Register trusted IdPs in org settings
- Configure claim mappings
- Test JWKS connectivity
-
Error Handling (RFC 6749 §5.2)
- Proper error codes for all failure modes
- Descriptive error messages
-
Testing
- Unit tests for JWT validation
- Integration tests with mock IdP
- Key rotation handling
P2 - Medium
-
JWKS Endpoint (
/.well-known/jwks.json)- For mutual trust scenarios
- Key rotation support
-
Monitoring
- Metrics for ID-JAG grants
- Alerting on validation failures
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 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/caching
New 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 pattern