Accept Per-User API Keys from Willow
When an MCP server is set to Proxy API Key, each user supplies their own key when they connect, and Willow forwards that key to your server on every tool call. Your server reads the key and validates it against your own store. This page describes exactly what your server receives.
This page is the forwarding reference. For a step-by-step build with runnable code, see Tutorial: Build an API-Key MCP Server with Express.
What your server receives
By default, Willow sends the user's key as the raw value of the Authorization header, with no Bearer prefix:
Authorization: <user-api-key>
This happens even when no custom header is configured. If your server expects a bearer scheme or a different header, the admin adds a custom header in the server's MCP configuration that references the key with a placeholder:
{{apiKey}}for the user's single key (the default).{{<identifier>}}for a named setup key, where<identifier>is the key identifier the admin defined.
For example, this MCP configuration also sends the key as X-Api-Key:
{
"type": "http",
"url": "https://mcp.example.com/mcp",
"headers": {
"X-Api-Key": "{{apiKey}}"
}
}
With that configuration, your server receives both headers, each carrying the same user key:
Authorization: <user-api-key>
X-Api-Key: <user-api-key>
Custom headers are additive: they do not replace the default Authorization injection. Read whichever header suits your server, but be aware the key also arrives in Authorization unless you account for it.
The placeholder is substituted with each user's own key at request time. If a user has not completed the connection and has no key bound, Willow forwards the placeholder text literally (for example {{apiKey}}) and your server receives that string. Reject values that still contain {{ rather than treating them as a key.
Validate the key
- Read the key from
Authorization(or your custom header). - Strip a
Bearerprefix only if you configured one; by default there is none. - Look the key up in your own store and authorize the request against that user's permissions.
- Reject missing, unknown, or unsubstituted (
{{...}}) values.
The key is the user's own credential for your service, not a token Willow issued, so validation is entirely against your system.
Per-user keys versus shared secrets
The {{apiKey}} and {{<identifier>}} placeholders resolve to each user's own key. They are different from a vault secret referenced as {{vault.SECRET_NAME}}, which is a single admin-managed value shared across all users. Use per-user keys when each user authenticates as themselves, and a vault secret when the whole organization shares one credential.