In our last post, we ran 180 AI agent shopping sessions across 11 models and 20 live stores. Every single session was anonymous. The agent connected, searched the catalog, built a cart, reached checkout — and the merchant had no idea who the buyer was.
That's fine for product discovery. It's a dead end for real commerce.
Without identity, there's no loyalty pricing. No saved addresses. No order history. No way to say "ship it to the same place as last time." The agent collects buyer info from scratch every session — name, email, phone, shipping address — adding 4-5 messages before checkout can even start. In our 180-session dataset, that friction was consistent across every model and every store.
So we built identity linking into UCP Playground.
What changed in the spec
On March 18, a breaking change landed in the UCP repository: feat!: redesign identity linking with mechanism registry and capability-driven scopes. Identity linking — dev.ucp.common.identity_linking — is now one of four core capabilities in the UCP spec, alongside Checkout, Order, and Payment Token Exchange.
Two concepts from this redesign matter for anyone building against UCP:
Mechanism registry. Merchants declare which authentication mechanisms they support in a structured registry within their UCP manifest. The registry pattern supports multiple mechanisms and can evolve without breaking existing implementations.
Capability-driven scopes. OAuth scopes are no longer static. A merchant might require one set of scopes for catalog access and a different set for checkout. The agent negotiates what it needs based on the capabilities it wants to use. An agent that only browses the catalog doesn't get checkout permissions. Least-privilege, applied to commerce.
What we built
We implemented the full OAuth 2.0 Authorization Code flow with PKCE in UCP Playground. Here's what the architecture looks like:
UCP Identity Linking — OAuth 2.0 PKCE Flow
Five steps, three actors. The agent never sees user credentials. The human stays in the loop at the consent step. Here's how each piece works in practice:
1. Discovery
When you point the playground at a merchant domain, we read the UCP manifest. If it declares dev.ucp.common.identity_linking and includes OAuth endpoints — authorization URL, token URL, and optionally a client registration URL — we light up the identity flow.
This is the same manifest we're already parsing for checkout and catalog capabilities. Identity linking is just another capability declaration, which means the discovery infrastructure we built for our 2,000-manifest monitoring works here too.
2. Dynamic client registration (RFC 7591)
This was the first surprise. The spec supports RFC 7591 dynamic client registration. Instead of manually registering an OAuth app at every merchant — which doesn't scale when you're testing against 20+ stores — the agent sends a registration request and gets client credentials back automatically.
In our IdentityLinkingService, this is a single POST:
$response = Http::post($registrationUrl, [
'client_name' => 'UCP Playground',
'redirect_uris' => [$callbackUrl],
'grant_types' => ['authorization_code'],
'response_types' => ['code'],
'token_endpoint_auth_method' => 'none', // public client
]);
We cache the registration per merchant so subsequent sessions reuse the same client credentials. No developer portal visits. No API key management. The protocol handles it.
3. PKCE authorization
PKCE (Proof Key for Code Exchange) prevents authorization code interception. We generate a random code verifier, hash it to create a challenge, and send the challenge with the authorization request. When we exchange the code for tokens later, we prove we're the same client by presenting the original verifier.
$verifier = Str::random(128);
$challenge = rtrim(strtr(
base64_encode(hash('sha256', $verifier, true)),
'+/', '-_'
), '=');
The user sees the merchant's consent screen — what permissions are being requested, what data will be shared. The agent can't bypass this. This is the critical trust boundary: the human explicitly approves what the agent can do on their behalf.
4. Token exchange
After consent, the merchant redirects back with an authorization code. We exchange it server-side with the PKCE verifier to prove the code belongs to us. Back comes an access token and a refresh token.
We built an OAuthTokenManager that handles refresh automatically. When a token expires mid-session, the manager swaps it transparently so the agent flow doesn't break. In practice, this means a user can link their identity once and the agent maintains the connection across multiple interactions.
5. Profile resolution
With a valid token, we call the merchant's profile endpoint. Back comes the buyer's identity — name, email, phone, shipping address. This is what flows into checkout instead of the manual 4-5 message collection.
One thing we learned building this: profile response formats vary across merchants. Some return flat JSON, some nest address fields, some use different key names for the same data. Our IdentityLinkingService normalizes across formats so the agent always gets a consistent buyer profile regardless of the merchant's implementation.
What we learned
Building this end-to-end surfaced a few things that aren't obvious from reading the spec:
Dynamic client registration is the unlock. Without RFC 7591, every platform building agent commerce would need to manually register OAuth apps at every merchant. That's the same integration bottleneck UCP was designed to eliminate. Dynamic registration makes the whole flow self-bootstrapping.
PKCE is non-negotiable. The spec requires it, and rightly so. Agents are effectively public clients — they can't securely store a client secret. PKCE ensures the authorization code can only be exchanged by the client that initiated the flow. Standard security practice, but it's good to see it baked into the spec rather than left as optional.
Capability-driven scopes add real complexity. Static scopes are straightforward — you request a list and you're done. Capability-driven scopes mean the agent needs to understand what capabilities it wants to use before requesting authorization. We built scope negotiation into the authorization step, but this is an area where fragmentation could emerge as different merchants define different scope mappings.
Profile normalization is unglamorous but essential. Every merchant returns buyer data slightly differently. If you don't normalize at the protocol layer, every agent has to handle format differences. We centralized this in one service, but the spec could benefit from stricter response format requirements.
The impact on agent sessions
Here's the practical difference. In our anonymous shopping sessions, the checkout flow looked like this:
Agent: I'd like to check out. What information do you need?
[Merchant requests: email, name, shipping address, phone]
Agent: What's your email?
User: user@example.com
Agent: Shipping address?
User: 123 Main St...
Agent: Phone number?
...
Four to five back-and-forth messages before the cart even moves toward payment. With identity linking:
Agent: [resolves buyer profile via OAuth token]
Agent: Ready to check out with your saved details. Proceed?
User: Yes.
Zero friction. The agent already knows who you are and where to ship. It's the difference between an agent shopping for you and an agent shopping as you.
Where adoption stands
We monitor 3,000+ domains through UCP Checker. Identity linking is starting to appear in merchant manifests, but most implementations are still at the declaration stage — merchants list the capability without fully wiring up the OAuth flow behind it.
In our audit system, identity linking earns 2 points in the manifest capability score. If a merchant declares it but their runtime tools don't support buyer identity fields, we flag it as a gap. We're scoring declaration today; runtime probing of OAuth endpoints is on our roadmap.
The infrastructure is ready on the platform side. We're waiting for merchants to plug in.
What to watch
Merchant adoption. Platforms like Shopify already run extensive OAuth infrastructure for their app ecosystem. Extending it to UCP identity linking is a natural step. Custom platform developers building against the spec will likely move faster.
Scope standardization. The capability-driven scopes model is powerful but new. As more merchants implement it, patterns will emerge. Early standardization prevents fragmentation.
The mechanism registry evolving. OAuth 2.0 is the starting point, but the registry is designed for more. Passkeys, verifiable credentials, federated identity — the architecture is there.
Check your domain: ucpchecker.com/check
Test the full flow: ucpplayground.com
Read the spec: github.com/Universal-Commerce-Protocol/ucp
Follow the data: ucpchecker.com/blog

Top comments (0)