Skip to content

feat(identity): let extensions register their own UCP OAuth scopes - #250

Merged
Björn Meyer (BrocksiNet) merged 3 commits into
mainfrom
claude/shopware-oauth-scope-extension-fce26c
Sep 25, 2026
Merged

Björn Meyer (BrocksiNet) merged 3 commits into
mainfrom
claude/shopware-oauth-scope-extension-fce26c

Conversation

@HoelShare

Copy link
Copy Markdown
Contributor

The grantable scopes were a private class constant on ShopwareIdentityLinkingAdapter, so a plugin adding a UCP capability of its own had no way to make its scope grantable: the authorization request threw Unsupported OAuth scope. A consent flow that catches that exception has already burned its one-time handle by then, so the buyer is told the authorization link expired -- indistinguishable from a real expiry, and two consent links were lost to it before the cause was found.

UcpOAuthScopeRegistry now merges the plugin's own scopes with those returned by every service tagged swag_agentic_commerce.ucp.oauth_scope_provider, the same tagged-iterator mechanism the product-export providers already use. The adapter advertises the merged set in scopes_supported on /.well-known/oauth-authorization-server and validates against it, so an agent can discover a scope before requesting it.

The three built-in scopes are unchanged, an empty scope request still expands to every supported scope, and an unregistered scope is still rejected -- now with the supported set named in the message, which is what made this hard to diagnose.

AbstractUcpOAuthScopeProvider is the plugin's second public PHP extension point and is documented in docs/public-api-boundaries.md.

@BrocksiNet

Copy link
Copy Markdown
Contributor

Should an omitted scope continue to grant only the three built-in scopes, with extension scopes requiring an explicit request? Expanding it to every registered scope means installing an extension also broadens the permissions granted to existing clients that omit scope, even though their authorization requests haven't changed.

The grantable scopes were a private class constant on
ShopwareIdentityLinkingAdapter, so a plugin adding a UCP capability of its own
had no way to make its scope grantable: the authorization request threw
`Unsupported OAuth scope`. A consent flow that catches that exception has
already burned its one-time handle by then, so the buyer is told the
authorization link expired -- indistinguishable from a real expiry, and two
consent links were lost to it before the cause was found.

UcpOAuthScopeRegistry now merges the plugin's own scopes with those returned by
every service tagged `swag_agentic_commerce.ucp.oauth_scope_provider`, the same
tagged-iterator mechanism the product-export providers already use. The adapter
advertises the merged set in `scopes_supported` on
/.well-known/oauth-authorization-server and validates against it, so an agent
can discover a scope before requesting it.

The three built-in scopes are unchanged, an empty scope request still expands to
every supported scope, and an unregistered scope is still rejected -- now with
the supported set named in the message, which is what made this hard to
diagnose.

AbstractUcpOAuthScopeProvider is the plugin's second public PHP extension point
and is documented in docs/public-api-boundaries.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Expanding an empty scope to every registered scope meant installing an
extension widened what an unchanged client that omits `scope` is granted.
An omitted scope now gets the three core scopes, as before the extension
point existed; an extension scope has to be requested by name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@HoelShare
Sebastian Hölscher (HoelShare) force-pushed the claude/shopware-oauth-scope-extension-fce26c branch from 7e01ac2 to 0f90560 Compare September 23, 2026 11:14
@HoelShare

Copy link
Copy Markdown
Contributor Author

Good point Björn Meyer (@BrocksiNet). I've adjusted so only the core scopes are granted!

Comment thread CHANGELOG_de-DE.md Outdated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@BrocksiNet
Björn Meyer (BrocksiNet) merged commit dd28c13 into main Sep 25, 2026
27 checks passed
@BrocksiNet
Björn Meyer (BrocksiNet) deleted the claude/shopware-oauth-scope-extension-fce26c branch September 25, 2026 07:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants