8 min read

How to Fix UCP Identity Linking Broken - Complete Guide (2026)

Your store handles transactions but every customer is treated as anonymous. Fix broken Identity Linking so AI agents can access saved addresses, loyalty, and order history.

How to Fix "UCP Identity Linking broken" - Complete Guide (2026)

Your UCP manifest passes structural checks. Payment handlers are correct. The agent can discover your store, browse your catalog, and add items to cart. But when it tries to access the user's saved addresses, loyalty points, or order history, everything falls apart. The reason: your Identity Linking capability is broken or missing.

This is the gap between "transactional commerce" and "personalized commerce." AI agents without identity linking treat every user as anonymous, even when they've shopped your store for years. Here's how to fix it.

What is UCP Identity Linking?

Identity Linking (dev.ucp.common.identity_linking) is the UCP capability that enables an AI agent platform (like Google or ChatGPT) to obtain authorization to act on behalf of a user on your store. It bridges agent-authenticated access to user-authenticated access.

Without Identity Linking, every interaction is anonymous:

  • An agent can browse your public catalog
  • An agent can add items to cart
  • An agent cannot access saved addresses, wishlists, loyalty benefits, or order history
  • Every purchase is a "new customer" transaction

With Identity Linking working correctly, the agent can:

  • Retrieve the user's saved shipping addresses and payment methods
  • Apply loyalty points or member pricing
  • Access purchase history for reordering
  • Show personalized recommendations
  • Complete the checkout as a recognized, authenticated customer

The v1 specification uses OAuth 2.0 Authorization Code flow as the authentication mechanism. Your store acts as the OAuth authorization server; the agent platform acts as the client.

Why this breaks AI agent experiences

When Identity Linking is broken, AI agents don't just get an error - they get downgraded to a worse shopping experience. Here's what happens:

  1. Agent discovers your store and reads the Identity Linking capability in your manifest
  2. Agent attempts to initiate the OAuth flow to link the user's identity
  3. The flow fails - authorization server metadata is missing, PKCE is not enforced, or scope tokens don't match
  4. Agent falls back to anonymous access mode
  5. User's saved preferences, loyalty discounts, and address are all invisible
  6. Agent presents a generic, unpersonalized shopping experience - or skips your store for one that does recognize the user

The worst part: this failure is silent from your perspective. Your store works fine for human shoppers. Your UCP endpoints return 200. But AI agents are presenting a degraded experience to your best customers - the ones who should be recognized and rewarded, not treated like strangers.

The 5 types of Identity Linking failures

1. Missing Identity Linking capability entirely

{
  "capabilities": {
    "checkout": { ... },
    "payment": { ... }
  }
}

No Identity Linking block exists at all. Agents cannot link user identities. While not strictly a "failure" (Identity Linking is technically optional), missing it means you forfeit personalized commerce entirely. For stores with loyalty programs, member pricing, or repeat customer volume, this is functionally a failure.

2. Missing authorization server metadata

{
  "capabilities": {
    "dev.ucp.common.identity_linking": {
      "spec_origin": "https://ucp.dev",
      "endpoint": "https://yourstore.com/api/ucp/identity"
    }
  }
}

The Identity Linking capability is declared but points to an endpoint instead of an OAuth authorization server. The UCP spec requires your store to publish authorization server metadata at /.well-known/oauth-authorization-server - which the agent needs to discover token endpoints, supported scopes, and authentication methods. Without this metadata, agents cannot complete the OAuth flow.

The fix: publish a complete OAuth authorization server metadata document, not just an endpoint reference.

3. Scope mismatches

Your manifest declares scopes the agent needs (like profile:read, orders:history, addresses:read), but your authorization server doesn't actually honor them. Or worse - your manifest declares one set of scopes and your authorization server advertises a different set in scopes_supported.

{
  "capabilities": {
    "dev.ucp.common.identity_linking": {
      "spec_origin": "https://ucp.dev",
      "config": {
        "scopes": ["profile:read", "orders:history", "addresses:read"]
      }
    }
  }
}

If your authorization server's scopes_supported field lists ["profile:read", "openid"] but your manifest declares ["profile:read", "orders:history", "addresses:read"], the agent will request scopes your server rejects. This causes the OAuth flow to fail at the authorization step.

4. PKCE not enforced

UCP spec requires PKCE (Proof Key for Code Exchange, code_challenge_method=S256) for all authorization code exchanges. If your authorization server doesn't validate code_verifier at the token endpoint, the agent's token request may still succeed - but it means your implementation is spec-noncompliant and vulnerable to authorization code interception.

# What the spec mandates:
Authorization request: code_challenge=XXX&code_challenge_method=S256
Token request:         code_verifier=YYY
Server MUST:           validate that code_challenge == SHA256(code_verifier)
Server MUST:           reject requests without a valid code_verifier

Agents may detect missing PKCE enforcement during security validation and refuse to complete the flow, even if your server would accept the request.

5. Redirect URI mismatch

The most common cause of broken Identity Linking. Your authorization server's redirect_uris list doesn't include the redirect URI the agent platform uses after authorization.

// Your server only allows:
{
  "redirect_uris": ["https://yourstore.com/oauth/callback"]
}

// But the agent is redirecting to:
// https://agent-platform.example.com/oauth/return

// Result: redirect_uri mismatch. Flow aborted.

The exception: loopback redirects (targeting 127.0.0.1) are handled differently per RFC 8252 Section 7.3. For loopback URIs, your server must match on scheme, host, and path only - ignoring the port component.

How to fix Identity Linking

Fix 1: Publish authorization server metadata

Create a complete OAuth authorization server metadata document at /.well-known/oauth-authorization-server:

{
  "issuer": "https://yourstore.com",
  "authorization_endpoint": "https://yourstore.com/oauth/authorize",
  "token_endpoint": "https://yourstore.com/oauth/token",
  "token_endpoint_auth_methods_supported": ["private_key_jwt", "client_secret_basic"],
  "scopes_supported": ["profile:read", "orders:history", "addresses:read", "loyalty:read"],
  "response_types_supported": ["code"],
  "code_challenge_methods_supported": ["S256"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "revocation_endpoint": "https://yourstore.com/oauth/revoke"
}

Without this metadata, agents have no way to discover your token endpoints, supported scopes, or authentication methods. The flow fails before it begins.

Fix 2: Align scopes between manifest and authorization server

The scopes in your UCP manifest's config.scopes array must match what your authorization server actually supports in scopes_supported:

// In your UCP manifest:
{
  "capabilities": {
    "dev.ucp.common.identity_linking": {
      "spec_origin": "https://ucp.dev",
      "endpoint": "https://yourstore.com/api/ucp/identity",
      "config": {
        "scopes": ["profile:read", "orders:history", "addresses:read", "loyalty:read"]
      }
    }
  }
}

// Your authorization server metadata MUST include:
// "scopes_supported": ["profile:read", "orders:history", "addresses:read", "loyalty:read"]

The spec explicitly calls this out: "publish scopes_supported metadata to allow platforms to detect scope mismatches before initiating an authorization flow." If they don't match, the agent will either fail mid-flow or request scopes your server rejects.

Fix 3: Enforce PKCE

Implement PKCE validation at your token endpoint:

  1. Authorization endpoint: Accept code_challenge and code_challenge_method parameters
  2. Store: Persist code_challenge with the authorization code
  3. Token endpoint: Require code_verifier parameter
  4. Validate: SHA256(code_verifier) must equal the stored code_challenge
  5. Reject: Return invalid_grant if code_verifier is missing or doesn't verify
# Server-side validation logic (pseudocode):
stored_challenge = retrieve_code_challenge(authorization_code)
computed_challenge = base64url(sha256(code_verifier))

if computed_challenge != stored_challenge:
    return error("invalid_grant", "code_verifier does not match code_challenge")

Fix 4: Configure redirect URIs correctly

Your authorization server must accept the redirect URIs used by AI agent platforms. Update your server's redirect_uris configuration:

{
  "redirect_uris": [
    "https://yourstore.com/oauth/callback",
    "https://accounts.google.com/oauth/return",
    "https://chatgpt.com/oauth/callback"
  ]
}

For loopback URIs (native/desktop agent runtimes), match on scheme, host, and path only:

# Agent redirects to: http://127.0.0.1:54321/callback
# Your server must match: http://127.0.0.1/callback (ignore port)

# Per RFC 8252 Section 7.3: loopback URIs are exempt from exact port matching

Fix 5: Add Issuer validation

Agents must validate the iss parameter in the authorization response to prevent Mix-Up Attacks:

# Authorization response includes:
# iss=https://yourstore.com

# Agent validates:
# if iss != authorization_server_metadata.issuer:
#     abort ("issuer mismatch - possible Mix-Up Attack")

# Your server MUST:
# Include the iss parameter in every authorization response
# Ensure iss matches your authorization server metadata.issuer exactly

How to test your fix

Identity Linking spans all four validation levels:

  1. Structural (Level 1): Is the dev.ucp.common.identity_linking capability present with valid JSON? Are config.scopes declared?
  2. Rules (Level 2): Do config.scopes match scopes_supported in your authorization server metadata? Is the issuer field correct?
  3. Network (Level 3): Is /.well-known/oauth-authorization-server reachable over HTTPS? Do token and authorization endpoints return correct responses?
  4. SDK/Simulation (Level 4): Can an AI agent complete the full OAuth Authorization Code flow, obtain a token, and use it to access user-specific resources?

Level 1 and Level 2 catch missing capability blocks and scope mismatches. But Level 3 and Level 4 are where PKCE enforcement, redirect URI configuration, and token endpoint behavior are actually tested. A metadata document that looks correct on paper can still fail when an agent attempts the real flow.

Run a free 4-level validation at ucptools.dev to catch Identity Linking failures across all four levels - including the OAuth flow simulation that Level 4 provides.

Common related failures

If you're fixing Identity Linking, also check:

  • Missing signing_keys - agents need cryptographic verification before processing identity tokens. Identity Linking bridges authentication; signing_keys proves the transaction is legitimate
  • Namespace/origin mismatch - an Identity Linking capability declared under a mismatched origin is treated as untrusted by agents
  • Payment handlers configured - once the user is identified, the agent needs valid payment handlers to complete the purchase as that recognized user
  • Checkout capability complete - Identity Linking personalizes the experience, but the Checkout capability must actually process the personalized transaction

Quick reference: Identity Linking requirements

FieldRequired?FormatCommon Mistake
Capability blockTechnically optional, functionally essentialdev.ucp.common.identity_linkingMissing entirely for stores with loyalty/repeat customers
Authorization server metadataYes (for OAuth flow)/.well-known/oauth-authorization-server JSON documentDeclaring capability without publishing metadata
config.scopesMust match scopes_supportedArray of scope strings like ["profile:read", "orders:history"]Manifest declares scopes server doesn't support
PKCE enforcementRequired by speccode_challenge_method=S256, validate code_verifier at token endpointNot validating code_verifier, accepting requests without PKCE
Redirect URIsMust include agent platform URIsExact match for non-loopback, scheme+host+path for loopbackOnly allowing your own callback URL
Issuer validationRequired by speciss parameter in response must match metadata issuerMissing iss parameter in authorization response

Last updated: May 2026. UCP spec version 1.2. Identity Linking is the stable capability (dev.ucp.common.identity_linking) that enables user-authenticated commerce via OAuth 2.0 Authorization Code flow. Missing or broken Identity Linking does not prevent agent discovery - but it prevents personalized experiences that convert repeat customers.

← Back to Blog