-
Notifications
You must be signed in to change notification settings - Fork 0
Authentication
The full picture of which token flows where. There are several distinct auth contexts in this stack; getting them mixed up is a common source of confusion.
┌─────────────────┐ ┌──────────────────────────┐
│ AI agent │──────▶│ Medusa backend │
│ (UCP/ACP req) │ │ + agentic-commerce │
└─────────────────┘ │ plugin │
└─────────────┬────────────┘
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌──────────┐
│ Prism │ │ Stripe │ │ Other │
│ Gateway│ │ Connect│ │ payment │
│ │ │ ... │ │ handlers │
└────────┘ └────────┘ └──────────┘
Three distinct auth boundaries to understand.
How agents authenticate (or don't) when they hit the plugin's routes.
UCP is meant for crawl-style discovery. No auth on /.well-known/ucp or /ucp/* routes by default. Agents announce themselves with two recommended headers (per UCP spec):
UCP-Agent: <agent-name>/<version>
Request-Id: <uuid>
These are informational — used for logging and request correlation, not auth.
ACP's OpenAPI explicitly defines Bearer auth on every endpoint:
security:
- bearerAuth: []
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: API Key # the spec's name for the token
parameters:
Authorization:
name: Authorization
in: header
required: trueWhen agentic_commerce_api_key (the api_key plugin option, sourced from AGENTIC_COMMERCE_API_KEY env in Quick Start) is configured, all /acp/* routes require:
Authorization: Bearer <agentic_commerce_api_key>
The spec leaves token format and issuance up to the seller — the plugin accepts whatever string you set. It's a single shared secret per Medusa instance, not per-agent.
⚠️ Conformance note:api_keyis currently treated as optional at the plugin level — when unset, ACP routes serve unauthenticated requests. That's non-conforming with ACP (theAuthorizationparameter isrequired: truein the spec). Useful for dev/testing; always set it for any real ACP-spec-compliant deployment.
The plugin reads from Medusa's standard modules — cart, product, order, payment, region, etc. — using the request-scoped DI container. No tokens involved; this is in-process module resolution via container.resolve("cart") etc.
The plugin doesn't reach into Medusa's database directly or use Medusa's internal admin APIs. Everything goes through the public module services so module isolation works as designed.
Each handler authenticates to its upstream service independently. For Prism: X-API-Key: <PRISM_API_KEY> header. For a hypothetical Stripe handler: Authorization: Bearer <STRIPE_API_KEY>.
These secrets come from the handler's options block in medusa-config.ts:
{
resolve: "@financedistrict/medusa-plugin-prism-payment/modules/prism-payment-handler",
options: {
api_url: process.env.PRISM_API_URL,
api_key: process.env.PRISM_API_KEY, // ← the handler reads this
},
}Convention is for handlers to also fall back to process.env.<HANDLER>_API_KEY when no explicit option is passed (defense in depth) — see Build a Handler.
| Token | Where it lives | Sensitivity |
|---|---|---|
AGENTIC_COMMERCE_API_KEY |
Medusa env / secrets backend | Medium — agent-side ACP gate |
Per-handler API keys (PRISM_API_KEY, etc.) |
Medusa env, passed to handler module options | High — direct payment-provider access |
-
Forgetting
Authorization: Bearer ...on ACP requests. Returns 401. The agent must include the sameAGENTIC_COMMERCE_API_KEYvalue as the Bearer token. -
Confusing the
agentic_commerce_api_keywith handler API keys. Theagentic_commerce_api_keyis for agent → Medusa auth. Handler keys are for Medusa → upstream-service auth. Different boundaries, different tokens. -
Putting
PRISM_API_KEYin the plugin'sapi_keyoption. Wrong place. The plugin'sapi_keyis the ACP Bearer token; Prism's API key goes in the prism-payment-handler module'sapi_keyoption. - Expecting per-agent keys. The current ACP setup is one shared secret per Medusa instance. Per-agent issuance is out of spec scope and not implemented.
- Quick Start — where to set each env var
- Build a Handler — convention for env-var precedence in handlers
- UCP and ACP — protocol-level auth requirements