Skip to content

Identity Assertion JWT Authorization Grant (ID-JAG) Support #106326

@dcramer

Description

@dcramer

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:

  1. Developer clicks "Login with SSO" in Cursor → authenticates with Okta
  2. Cursor exchanges ID token for ID-JAG targeting Sentry
  3. Cursor presents ID-JAG to Sentry's token endpoint
  4. Sentry validates, maps user via SSO identity, issues org-scoped token
  5. 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 assertion parameter 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
  • ID-JAG Validation

    • Verify aud matches Sentry issuer
    • Verify client_id matches request authentication
    • Implement replay prevention via jti tracking
    • Scope intersection (ID-JAG × request × client × user)
  • Trusted IdP Configuration

    • Model for trusted IdP registration (TrustedIdentityProvider)
    • JWKS fetching with caching
    • Subject-to-user mapping via AuthIdentity
  • 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 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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions