Repository navigation
feat(oauth): Store scopes Sentry actually granted as upstreamScopes - #1561
Merged
Merged
Conversation
Sentry's OAuth token response includes the access token's real scopes in `scope`. The callback parsed it via TokenResponseSchema but discarded it, and only stored `grantedScopes`, which is derived from the selected skills and does not reflect what the upstream token can do. Persist the token response scope on the grant props as `upstreamScopes` (sorted, de-duplicated). Leave it undefined when Sentry omits the field so an absent value is not mistaken for "no scopes". `grantedScopes` is unchanged; this gives us data to decide whether to drop it. Co-Authored-By: shaun.kaasten <shaun.kaasten@sentry.io>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
BYK
approved these changes
Oct 21, 2026
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The OAuth callback stores
grantedScopeson grant props. The name suggests "scopes Sentry granted", but the value is computed locally bygetScopesForSkills(selectedSkills). It does not reflect what the stored Sentry token can actually do.Today the upstream authorize request asks for every scope in
SCOPES(org:read project:write team:write event:write alerts:write), whatever skills are selected. So an Inspect-only grant can have read-onlygrantedScopeswhile the Sentry token holds write scopes.Sentry's token response already reports the token's real scopes in
scope(Sentry builds it fromtoken.get_scopes(), andTokenResponseSchemaalready requires the field). The callback parsed that value and then discarded it.What
callback.ts: persist the token responsescopeon grant props asupstreamScopes. The list is split on whitespace, de-duplicated and sorted. If Sentry omitsscope, the field is leftundefinedso a missing value isn't mistaken for "no scopes".types.ts: addupstreamScopes?: string[]toWorkerProps, with a doc comment contrasting it withgrantedScopes.helpers.ts: carryupstreamScopesthrough token-exchange props explicitly, next tograntedScopes.docs/operations/security.mdanddocs/cloudflare/oauth-architecture.mdexplain the difference.grantedScopesis unchanged. Nothing readsupstreamScopesyet.Why stop here
This PR records the data, which helps decide whether to drop the misleadingly named
grantedScopes. Current runtime authorization usesgrantedSkills, and the MCP handler doesn't readgrantedScopes.Notes:
scopeon refresh anyway. The stored value therefore stays accurate for the life of the grant.upstreamScopesuntil users re-authorize.Tests
upstreamScopesfrom the token response, separate from skill-derivedgrantedScopes. Confirmed it fails without the change.upstreamScopesis omitted when the token response has noscope.@sentry/mcp-cloudflare: 435/435 pass. Typecheck, oxlint and oxfmt are clean.via shaun.kaasten.
--
View Junior Session [Sentry]