ai newsMo., 2. Nov.
EilmeldungHow I made a Game with Claude from scratch

How do AI agents authenticate? (The problem nobody has solved yet)

If you've built an MCP server or an API that agents call, you've run into this problem. Your agent needs to call a tool. That tool needs to know who's calling. So you do what everyone does: generate an API key, paste it in an env var, and move on. It works. Until it doesn't. The key gets committed

dev.toSonntag 22:02 · 01.11.4 Min. Lesezeit
Bild: dev.to

If you've built an MCP server or an API that agents call, you've run into this problem.

Your agent needs to call a tool. That tool needs to know who's calling. So you do what everyone does: generate an API key, paste it in an env var, and move on.

The key gets committed to a repo. Or it gets shared across a whole team's agents, so every agent looks identical in your logs. Or someone leaves and you realize you have no idea which credentials they had. Or you're running 50 agents and managing 50 sets of credentials per tool.

This isn't a process problem. It's an architectural one. API keys were designed for humans. They were never designed for machines.

Think about what authentication is supposed to do: prove that the entity making a request is who they say they are.

For humans, passwords work (barely) because you can reset them, remember them, and tie them to a person. For machines, a static shared secret is just a liability — it has to exist somewhere, which means it can leak from somewhere.

What agents need is proof of identity without a credential that can be stolen. That's a solved problem in cryptography. It's called a challenge-response. The server issues a one-time nonce. The client signs it with a private key. The server verifies the signature. No credential ever travels over the wire — only a signature that proves the client holds the key.

SSH works this way. TLS works this way. There's no reason agent authentication shouldn't.

Arken is an open-source implementation of this for HTTP APIs and MCP servers.

Each agent gets a key pair. The did:key identifier derived from that key pair is the agent's identity — a string that looks like did:key:zQ3sh.... It's deterministic from the private key, portable across every Arken-protected endpoint, and requires no registration with any central authority.

Server side — one line of Express middleware:

const { arkenAuth } = require ( ' @arkenforge/arken-auth ' ); app. get ( ' /tool ', arkenAuth (), ( req, res ) => { res. json ({ did: req. user. did }); }); Enter fullscreen mode Exit fullscreen mode An unsigned request gets a 401 with a one-time nonce:

{ "challenge": { "nonce": "a3f9...", "statement": "Sign this message to prove you control this DID." } } Enter fullscreen mode Exit fullscreen mode The client signs the nonce and retries with an Authorization: Signature header. The server verifies the ECDSA signature in Rust, consumes the nonce, and sets req.user.did. No credentials stored. Nonce expires in 60 seconds.

const { createClient } = require ( ' arken-client ' ); const { fetch, did } = createClient ( process. env. AGENT_PRIVATE_KEY ); console. log ( did ); // did:key:zQ3s… — same every time for this key const res = await fetch ( ' https://your-mcp-server.com/tool ' ); // 401 → sign → retry happens automatically // your code never sees the auth flow Enter fullscreen mode Exit fullscreen mode If no key is provided, one is generated. For agents that need a stable identity across runs, generate once and store the private key.

Every agent in your fleet has a unique did:key. When it calls a tool, the server logs exactly which DID called — not "some agent using the shared service token."

You can do things that were previously impossible with API keys:

from arken_auth import arken_auth @app.get ( " /tool " ) async def tool ( user = Depends ( arken_auth ())): return { " did ": user [ " did " ]} Enter fullscreen mode Exit fullscreen mode Production deployments By default nonces are stored in memory. For multi-instance deployments, pass a Redis client:

const { arkenAuth, RedisNonceStore } = require ( ' @arkenforge/arken-auth ' ); const { createClient } = require ( ' redis ' ); const redis = createClient ({ url: process. env. REDIS_URL }); await redis. connect (); app. use ( ' /tool ', arkenAuth ({ store: new RedisNonceStore ( redis ) })); Enter fullscreen mode Exit fullscreen mode Install npm install @arkenforge/arken-auth # server npm install arken-client # agent pip install arken-auth # FastAPI pip install arken-client # Python agents Enter fullscreen mode Exit fullscreen mode Pre-1.0 — the API may change before the stable release. Apache 2.0.

Agents proliferating without per-agent identity is going to cause problems. Most enterprises don't know which agents exist inside their infrastructure, what they're authorized to do, or what they've accessed. A shared service token doesn't tell you any of that.

A did:key per agent is the primitive that makes visibility possible — not just for security, but for billing, auditing, and access control.

If you're building MCP servers, agent backends, or APIs that agents call — especially if you've hit the credentials problem in production — I'd like to hear about your setup.

Quelle: dev.to (dev.to). Original öffnen