Skip to content

feat(support): Add Intercom backend for identity verification#108408

Open
sentaur-athena wants to merge 6 commits intomasterfrom
athena/intercom-backend
Open

feat(support): Add Intercom backend for identity verification#108408
sentaur-athena wants to merge 6 commits intomasterfrom
athena/intercom-backend

Conversation

@sentaur-athena
Copy link
Member

@sentaur-athena sentaur-athena commented Feb 17, 2026

End goal:
We want to replace Zendesk with Intercom in product. Here is a helpful diagram about how the pieces get connected in the end: https://www.notion.so/sentry/Migration-Plan-Zendesk-to-Intercom-Chat-in-Sentry-Product-30a8b10e4b5d807c9bcdef3105761dda?source=copy_link#30a8b10e4b5d80e7aa7af9b9a58f2c47

This PR:
Add backend support for Intercom messenger with JWT-based identity verification. Zendesk Auth was session based and didn't need this in the past which is why we need a new endpoint:

  • Add intercom.app-id and intercom.identity-verification-secret options
  • Create OrganizationIntercomJwtEndpoint for generating signed JWTs (docs)
  • Add INTERCOM grant type to DataAccessGrant model for ticket tracking
  • Update get_active_tickets_for_organization to include both providers
  • Add organizations:intercom-support feature flag for gradual rollout
  • Register /api/0/organizations/{org}/intercom-jwt/ endpoint

The JWT is signed with HS256 and includes user_id, email, name, and organization context. Tokens expire after 5 minutes for security.

The feature flag allows gradual rollout and serves as a killswitch to instantly revert to Zendesk without code deployment.

E2E testing:
Tested using ngrok and the next PR in stack. Request goes through in happy path denied from unknown domains.

@sentaur-athena sentaur-athena requested review from a team as code owners February 17, 2026 23:18
@github-actions github-actions bot added Scope: Backend Automatically applied to PRs that change backend components Scope: Frontend Automatically applied to PRs that change frontend components labels Feb 17, 2026
@github-actions
Copy link
Contributor

🚨 Warning: This pull request contains Frontend and Backend changes!

It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently.

Have questions? Please ask in the #discuss-dev-infra channel.

Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

sentaur-athena and others added 5 commits February 19, 2026 09:45
…ication

Add backend support for Intercom messenger with JWT-based identity verification:
- Add intercom.app-id and intercom.identity-verification-secret options
- Create OrganizationIntercomJwtEndpoint for generating signed JWTs
- Add INTERCOM grant type to DataAccessGrant model for ticket tracking
- Update get_active_tickets_for_organization to include both providers
- Add organizations:intercom-support feature flag for gradual rollout
- Register /api/0/organizations/{org}/intercom-jwt/ endpoint

The JWT is signed with HS256 and includes user_id, email, name, and
organization context. Tokens expire after 5 minutes for security.

The feature flag allows gradual rollout and serves as a killswitch
to instantly revert to Zendesk without code deployment.
Add isinstance check for AnonymousUser to narrow the type of request.user
for mypy, which sees it as User | AnonymousUser.
Register the endpoint pattern so the frontend routes requests correctly.
Fixes timing issue where third-party widgets (like Intercom) try to
access the DOM before it's ready, causing appendChild errors.
Copy link
Contributor

@michelletran-sentry michelletran-sentry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally LGTM. Just have a few questions.

)

# Intercom Integration
register("intercom.app-id", default="", flags=FLAG_PRIORITIZE_DISK | FLAG_AUTOMATOR_MODIFIABLE)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This currently looks unused. It looks like it's encoded into the frontend? Do we need this here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michelletran-sentry I have to register an env var for the app id and app secret. I actually don't know what's the best way, looks like it should live in getsentry looking at other existing code. Let me know if you know the answer: https://sentry.slack.com/archives/C039ZGT5K/p1772060405590499

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used here in the backend: https://github.com/getsentry/getsentry/pull/19394

Will remove it from this PR because at this point I think it belongs to getsentry.

claims = {
"user_id": str(user.id),
"email": user.email,
"name": user.get_display_name(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name claim looks like it's an optional claim in Intercom. Are we planning on enforcing it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I think we want it but shouldn't enforce it.



@control_silo_endpoint
class OrganizationIntercomJwtEndpoint(ControlSiloOrganizationEndpoint):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: do we need Organization in the class name? Maybe

Suggested change
class OrganizationIntercomJwtEndpoint(ControlSiloOrganizationEndpoint):
class IntercomJwtEndpoint(ControlSiloOrganizationEndpoint):

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

our endpoints that are like ../organization/{slug}/... are named organization endpoint. No strong opinion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants