{"slug": "how-we-solved-agent-auth-without-a-single-pat", "title": "How We Solved Agent Auth Without a Single PAT", "summary": "Mohamed Sherif and his team developed a TOFU-based authorization model for headless AI agents that replaces long-lived credentials with agent fingerprints. The system derives a fingerprint from the agent's runtime characteristics, requiring human approval on first access and issuing short-lived tokens for each session. This approach eliminates the need for Personal Access Tokens and service accounts, reducing security risks and credential sprawl.", "body_md": "A TOFU-based authorization model for headless AI agents\n\nBy Mohamed Sherif\n\nIf you’ve built an AI agent recently, you’ve probably run into the same problem.\n\nThe first integration is easy.\n\nYour agent needs access to GitHub, so you create a Personal Access Token (PAT), add it to .env, and move on.\n\nGITHUB_PAT=ghp_xxxxxxxxxxxx\n\nThen you add Slack.\n\nSLACK_BOT_TOKEN=xoxb-xxxxxxxxxxxx\n\nThen Notion.\n\nNOTION_TOKEN=secret_xxxxxxxxxxxx\n\nThen Linear.\n\nLINEAR_API_KEY=lin_api_xxxxxxxxxxxx\n\nBefore long your AI agent depends on a growing collection of long-lived credentials scattered across local environments, CI/CD pipelines, Kubernetes secrets, and production infrastructure.\n\nIt works.\n\nUntil it doesn’t.\n\n⸻\n\nThe Problem Every Agent Builder Eventually Hits\n\nTraditional software authenticates users.\n\nAI agents authenticate themselves.\n\nThat’s a subtle but important difference.\n\nOAuth was designed around a human sitting in front of a browser who can click Allow when an application requests access.\n\nAI agents don’t have browsers.\n\nThey don’t have users.\n\nThey don’t have anyone available to approve access while they’re running.\n\nMost developers eventually fall back to one of four patterns.\n\nFastest to build.\n\nAlso the easiest way to accumulate technical debt.\n\nYou end up with:\n\nThe “proper” solution.\n\nFor every provider you need to:\n\nRepeat this for every integration.\n\nYour authentication layer quickly becomes larger than the product you’re actually trying to build.\n\nAWS Secrets Manager, Vault, Azure Key Vault…\n\nThese solve storage.\n\nThey don’t solve authorization.\n\nSomeone still has to provision credentials.\n\nThe agent still eventually receives them.\n\nThere’s still no approval workflow and no way to distinguish one agent from another.\n\nConvenient.\n\nBut every agent sharing that account effectively becomes the same identity.\n\nIf one agent is compromised, every workload using that service account is affected.\n\n⸻\n\nWhat We Actually Wanted\n\nAfter looking at these approaches, we realized we wanted something fundamentally different.\n\nOur requirements were surprisingly simple.\n\nThat combination turned out to be harder than expected.\n\n⸻\n\nBorrowing an Idea from SSH\n\nThe breakthrough came from an unexpected place.\n\nSSH solved a very similar problem years ago.\n\nThe first time you connect to a server, SSH asks:\n\n“Do you trust this host?”\n\nIf you approve it, the server fingerprint is remembered.\n\nFuture connections are automatic.\n\nIf the fingerprint changes unexpectedly, SSH warns you.\n\nThis model is called Trust On First Use (TOFU).\n\nWe asked ourselves:\n\nWhat if AI agents worked the same way?\n\n⸻\n\nApplying TOFU to AI Agents\n\nInstead of trusting a server fingerprint, we trust an agent fingerprint.\n\nThe first time an unknown agent requests access to a connected service:\n\nVisually, the flow looks like this:\n\nDeveloper connects GitHub once\n\n│\n\n▼\n\nGateway stores OAuth credential\n\n│\n\n▼\n\nDeveloper gives agent one Passkey URL\n\n│\n\n▼\n\nAgent requests GitHub access\n\n│\n\n▼\n\nUnknown fingerprint?\n\n│\n\nYes ─────────► Human approval\n\n│\n\n▼\n\nFingerprint trusted\n\n│\n\n▼\n\nShort-lived token exchanged\n\n│\n\n▼\n\nAgent calls GitHub\n\nThe important distinction is what the agent doesn’t receive.\n\nIt never sees:\n\nInstead, it receives a short-lived token for the current session.\n\n⸻\n\nFingerprints Instead of Secrets\n\nEvery agent has an identity.\n\nRather than identifying it with a shared secret, we derive a fingerprint from characteristics of its runtime.\n\nThat fingerprint becomes the identity we authorize.\n\nThis enables several useful properties.\n\nAttribution\n\nEvery API request can be tied back to one specific agent identity.\n\nAudit\n\nYou know exactly which agent accessed which service and when.\n\nRevocation\n\nDeleting one trusted fingerprint immediately blocks that agent without rotating credentials or redeploying infrastructure.\n\nBlast Radius Reduction\n\nA compromised agent only affects itself.\n\nNot every deployment using the same credentials.\n\n⸻\n\nWhat Integration Looks Like\n\nConnecting a service happens once through the dashboard.\n\nAfter OAuth completes, the credential stays inside the gateway.\n\nThe agent configuration remains extremely small.\n\n{\n\n\"mcpServers\": {\n\n\"passkey\": {\n\n\"command\": \"npx\",\n\n\"args\": [\"passkey-mcp\"]\n\n}\n\n}\n\n}\n\nFrom the perspective of LangChain, CrewAI, Strands, Bedrock AgentCore—or any MCP-compatible framework—nothing changes.\n\nThe agent simply discovers tools like:\n\ngithub_*list_issues\ngithub*\n\nThe authentication layer becomes invisible.\n\n⸻\n\nWhy We Chose Token Exchange\n\nOne design decision deserves explanation.\n\nInstead of proxying every request, the gateway performs a token exchange.\n\nOnce authorized, the agent receives a short-lived upstream token.\n\nThe API traffic then goes directly to the provider.\n\nThat provides several advantages:\n\n⸻\n\nOther Design Decisions\n\nRotating Connection URLs\n\nConnection URLs use rotating slugs.\n\nCapturing yesterday’s URL isn’t enough to gain access.\n\nIt must also match a trusted fingerprint.\n\nDynamic Client Registration\n\nWhere supported, every customer receives their own OAuth client rather than sharing one across the platform.\n\nThat reduces rate-limit contention and isolates failures between organizations.\n\nMCP-Native\n\nRather than invent another SDK, we built around MCP.\n\nAny framework that already supports MCP can use the same authentication model without additional integration work.\n\n⸻\n\nWhen This Approach Makes Sense\n\nThis model is particularly useful if:\n\nIf you’re building a weekend project with one integration, a PAT is probably sufficient.\n\nOnce multiple integrations and production deployments enter the picture, the trade-offs begin to change.\n\n⸻\n\nTry It\n\nIf you’re interested in experimenting with this model, install the local broker:\n\nnpx passkey-mcp\n\nThen manage everything through:\n\nConnect your first OAuth provider through the Passkey dashboard, then point any MCP-compatible agent at it.\n\nToday the platform supports 19 integrations including GitHub, Slack, Jira, Confluence, Notion, Stripe, Salesforce, HubSpot, and Linear.\n\nI’d love to hear feedback from developers building production AI agents.\n\nThe biggest question we wanted to answer was simple:\n\nCan we eliminate long-lived credentials from AI agents without making developer experience worse?\n\nSo far, the answer has been yes.", "url": "https://wpnews.pro/news/how-we-solved-agent-auth-without-a-single-pat", "canonical_source": "https://dev.to/m_v2n2x/how-we-solved-agent-auth-without-a-single-pat-1fnd", "published_at": "2026-07-25 17:12:48+00:00", "updated_at": "2026-07-25 18:01:43.554398+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "ai-infrastructure", "developer-tools"], "entities": ["Mohamed Sherif", "GitHub", "Slack", "Notion", "Linear", "AWS Secrets Manager", "Vault", "Azure Key Vault"], "alternates": {"html": "https://wpnews.pro/news/how-we-solved-agent-auth-without-a-single-pat", "markdown": "https://wpnews.pro/news/how-we-solved-agent-auth-without-a-single-pat.md", "text": "https://wpnews.pro/news/how-we-solved-agent-auth-without-a-single-pat.txt", "jsonld": "https://wpnews.pro/news/how-we-solved-agent-auth-without-a-single-pat.jsonld"}}