Noizu.MCP.Auth.Server.ApiKeyTokenPlug (Noizu MCP v0.1.6)

Copy Markdown View Source

Trade a host API key for a short-lived, audience-bound access token — POST /api/mcp/token.

scope "/api/mcp" do
  pipe_through [:api, :rate_limited_auth]     # must skip protect_from_forgery
  forward "/token", Noizu.MCP.Auth.Server.ApiKeyTokenPlug, MCPConfig.as_opts()
end

A headless caller — a cron job, a CI step — cannot open a browser, and OAuth without a browser is not OAuth. This endpoint gives it the same kind of token every other client gets: same aud, same 15-minute ceiling, same scope rules.

Why not just accept the API key at the MCP mount?

You can — Noizu.MCP.Auth.ApiKeyVerifier in a ChainVerifier does exactly that, and for a single-mount host it is simpler. This endpoint is better when there are several mounts: the key is presented once, to one endpoint, and what travels to each mount afterwards is a token bound to that mount alone. A long-lived key presented on every request is a long-lived key in every log.

No refresh token is issued: the API key is the long-lived credential, and a caller that holds it can always ask again.

Options (api_keys: on the server config)

  • :validator (required) — {mod, fun} over the presented key, exactly as Noizu.MCP.Auth.ApiKeyVerifier uses it
  • :prefix, :keys, :default_claims, :scopes — passed straight through
  • :client_id — the client_id recorded on issued tokens, default "api-key"

The rate-limit hook fires as :api_key_token. Rate limiting here is the point: without it this endpoint is an offline-free API-key oracle.