Open-source auth where AI agents are first class.
Agent identity, delegation with live revocation and an MCP OAuth 2.1 server, next to the usual human sign in. One TypeScript library, self-hosted, MIT licensed.
Website · Quickstart · Docs · Examples · Discussions · GLINR Discord
theAuth is auth for products where AI agents act on behalf of people. Each agent gets its own identity and a bearer token, scoped permissions, an owner, and an audit row for every decision. An agent can hand a subset of its permissions to another agent, and revoking any link in that chain takes effect on the next call. It includes an OAuth 2.1 authorization server for MCP, and the usual human sign in: email and password, magic links, passkeys, TOTP, 48 OAuth providers, SAML and OIDC SSO, SCIM.
It runs on Node, Bun, Deno and Cloudflare Workers with four runtime dependencies (drizzle-orm, jose, sql.js, zod). No hosted service is required. The project was called kavachOS until 2026, see the rename map if you have older code.
Devices and robots use the same model. A sensor, gateway or machine can hold its own credentials (a pre shared key, a signing key or a TLS client certificate), enroll with a claim code or a bulk token, and be revoked live. For ROS 2, theauth ros2 export writes the SROS2 and DDS Security files from the robot's permissions, and a gate node asks theAuth before a hazardous command is published. theAuth is not a safety system, so emergency stops stay in the robot's safety controller.
Needs Node 20 or newer. This runs as pasted, with an in-memory SQLite database.
npm install @glinr/theauthimport { createTheAuth } from "@glinr/theauth";
const auth = await createTheAuth({
database: { provider: "sqlite", url: ":memory:" },
agents: { enabled: true },
});
// An agent needs an owner row. Human sign in creates these for you.
const owner = await auth.user.create({ email: "owner@example.com", name: "Owner" });
const agent = await auth.agent.create({
ownerId: owner.id,
name: "github-reader",
type: "autonomous",
permissions: [{ resource: "mcp:github:*", actions: ["read"] }],
});
console.log(agent.token); // starts with "ta_", shown once
const read = await auth.authorize(agent.id, { action: "read", resource: "mcp:github:repos" });
console.log(read.allowed, read.code);
const write = await auth.authorize(agent.id, { action: "write", resource: "mcp:github:repos" });
console.log(write.allowed, write.code);Output from a real run (the token differs each time):
ta_2_wqD8Yoenc_LDoFMTdKkQ9YXQNuW-rWxHHyfmKJJOo
true allowed
false no_permission
Tokens from before the rename start with kv_ and are still accepted. To serve this over HTTP, add a framework adapter. For email and password, install @glinr/theauth-email. To scaffold an app, run npm create @glinr/theauth-app. Full walkthrough: quickstart.
- Delegation chains with live revocation. An agent delegates part of what it holds to another agent, with depth limits and expiry. If a delegator is revoked, suspended or expired, the agents below it stop borrowing its permissions. See delegation.
- MCP tokens bound to their authority. Tokens from token exchange carry the agent path and delegation link ids. Revoking a link, an agent, a session or a single token fails the next MCP request on every instance that shares the database. Three freshness modes trade latency for staleness: MCP revocation.
- Hooks that fail closed. A
beforeAuthorizehook that throws, times out (2000 ms by default) or returns a malformed verdict denies the call. You can plug in an external guard over HTTPS with signed requests and responses: hooks, remote guards. - Decision codes and explain.
authorize()returns a machine-readablecodesuch asno_permissionorhook_denied.explain()says which rule or delegation link carried a call, with no side effects: explain, errors. - Tamper-evident audit. Turn on the hash chain and an edited, deleted or reordered row shows up on the next verify. Signed checkpoints and receipts can be checked offline, including by the Go library: audit trail, receipts.
Maturity follows the package version: stable is 1.0 or later, beta is 0.2 to 0.9, experimental is 0.1. The core package is at 2.0.0. If you run 1.x, read Upgrading to 2.0 if you run 1.x.
What you should know before relying on it:
- SAML is experimental. The verifier is our own code, built on Web Crypto. It passes tests against xmllint and xml-crypto output and has had no independent audit. If you need an audit today, put an audited SAML library in front and pass the identity to your own session code.
- The cookie session cache is experimental and opt in. It can lag a revocation by up to its
maxAge. See session hardening. - MySQL is not supported.
provider: "mysql"throws unless you passexperimental: true, and the baseline schema does not apply on a real server yet. - Postgres is tested by hand, not in CI. The full suite runs against Postgres 14 before each release. Only the
pgdriver is supported. - D1 is not tested in CI or by hand yet. The generated SQLite SQL is applied with
skipMigrations: true. - Client ID metadata documents (CIMD) on Workers and Deno. Deno uses
node:dnslike Node. Workers needcreateDohResolver(), or"none"withallowedHosts. DNS rebinding cannot be fully closed withoutallowedHosts. See CIMD.
| Provider | Use it for | Tested in CI |
|---|---|---|
sqlite (sql.js) |
Tests, CI, demos. In memory only. | Yes |
sqlite-native (better-sqlite3) |
One process, a database file on disk. | Yes |
postgres (pg) |
Several instances or real traffic. | No, run by hand |
d1 |
Cloudflare Workers. | No |
mysql |
Not supported. | No |
The Prisma adapter reads and writes theAuth tables from code that already uses Prisma. Picking a store and a secondary store: choose storage.
All packages live in this monorepo and publish under @glinr/. Versions come from each package.json.
| Package | Version | Maturity | What it does |
|---|---|---|---|
theauth |
2.0.0 | Stable | Agent identity, delegation, MCP OAuth 2.1 server, DPoP, passkeys, audit |
theauth-email |
4.1.1 | Stable | Email and password sign in |
theauth-mcp |
2.0.0 | Stable | Read-only MCP server to inspect agents, permissions and audit |
theauth-gateway |
4.2.0 | Stable | Auth proxy in front of any API or MCP server |
theauth-cli |
1.3.0 | Stable | init, doctor, migrations, dashboard (also npx theauth) |
theauth-client |
1.2.0 | Stable | TypeScript client for the REST API |
theauth-plugin-discovery |
4.0.2 | Stable | A2A agent card discovery |
theauth-plugin-telemetry |
4.1.0 | Stable | OpenTelemetry spans from auth events |
theauth-react |
0.8.0 | Beta | React hooks |
theauth-vue |
0.4.0 | Beta | Vue 3 composables |
theauth-svelte |
0.4.0 | Beta | Svelte stores |
theauth-expo |
0.5.0 | Beta | React Native and Expo client |
theauth-electron |
0.4.0 | Beta | Electron client |
theauth-ui |
0.4.0 | Beta | Prebuilt auth components |
theauth-ui-headless |
0.2.0 | Beta | Unstyled account components |
theauth-dashboard |
0.4.0 | Beta | Admin UI for agents, permissions and audit |
theauth-agent-frameworks |
0.2.0 | Beta | Tool guard with human approval for LangChain.js, LangGraph and Mastra |
theauth-conformance |
0.3.0 | Beta | Black-box conformance suite for OAuth 2.1 and MCP servers |
theauth-test-utils |
0.3.0 | Beta | Mock providers, factories and assertions |
create-theauth-app |
0.6.0 | Beta | Scaffold an app |
theauth-extension |
0.1.0 | Experimental | OAuth 2.1 for Manifest V3 browser extensions |
Other languages: a Go client and a Python client (source) for this REST API, both checked against the generated sdks/openapi.json, and a Terraform provider (source). theauth-go is a different thing: the Go server library (v2), not a client for this API.
Every adapter wraps one core handler, so all of them serve the same routes with the same status codes (route reference).
| Adapter | Version | Docs |
|---|---|---|
theauth-hono |
6.0.0 | Hono |
theauth-nextjs |
6.0.0 | Next.js |
theauth-express |
6.0.0 | Express |
theauth-fastify |
6.0.0 | Fastify |
theauth-nestjs |
6.0.0 | NestJS |
theauth-nuxt |
6.0.0 | Nuxt |
theauth-sveltekit |
6.0.0 | SvelteKit |
theauth-astro |
6.0.0 | Astro |
theauth-solidstart |
6.0.0 | SolidStart |
theauth-tanstack |
6.0.0 | TanStack Start |
theauth-prisma |
4.1.0 | Prisma |
theauth-nextjs-auth |
0.2.0 (beta) | Next.js client for external auth backends |
Mounting Hono, for example:
import { Hono } from "hono";
import { createTheAuth } from "@glinr/theauth";
import { theAuthHono } from "@glinr/theauth-hono";
const auth = await createTheAuth({
database: { provider: "postgres", url: process.env.DATABASE_URL! },
});
const app = new Hono();
app.route("/api/theauth", theAuthHono(auth, { authenticate }));authenticate resolves the caller from the request, see the Hono guide. Working examples are in examples/.
- Quickstart and core concepts
- MCP OAuth 2.1 server and MCP revocation
- Delegation, guards and hooks
- Observability, audit trail and audit receipts
- IoT devices and robotics and ROS 2
- Upgrading to 2.0 for people on 1.x
- Works with, migrating from another library and the API reference
- Security policy
Generated by node scripts/stats.mjs into docs/stats.json.
- 48 OAuth providers: 22 first class and 26 presets
- 10 framework adapters
- 4 runtime dependencies in core
- About 5,277 test cases in 410 test files (a textual count of
it(andtest(calls, so approximate)
Questions and ideas go to GitHub Discussions or the #theauth channel in the GLINR Discord. Changes are listed in CHANGELOG.md. To contribute, see CONTRIBUTING.md; everyone is held to the Code of Conduct.
Report vulnerabilities privately to support@glinr.com or through the GitHub advisory form. Do not open a public issue. Details in SECURITY.md.
MIT. Built in the open by GLINCKER, a GLINR STUDIOS company.