Authentication built for AI agents.
OAuth for AI agents. Secure infrastructure for AI-to-API access.
Quick Start • Features • Dashboard • API • SDKs • Deploy
MachineAuth provides authentication and permission infrastructure that allows AI agents to securely access APIs, tools, and services.
MachineAuth is OAuth for AI agents.
AI agents are starting to interact with the real internet. They call APIs, trigger workflows, access data, and automate tasks. But today's authentication systems were designed for humans, not autonomous software.
MachineAuth solves this. We provide secure identity, permission, and access control for AI agents — allowing them to safely interact with APIs and external services. With MachineAuth, developers can give AI agents controlled access to tools without exposing API keys or risking misuse.
| Problem | MachineAuth Solution |
|---|---|
| Sharing long-lived API keys | Short-lived JWTs with configurable expiry |
| No credential rotation | One-click rotation, zero downtime |
| No visibility into agent activity | Per-agent usage tracking, audit logs, metrics |
| Complex auth infrastructure | Single binary, JSON file storage for dev, Postgres for prod |
| No webhook notifications | Built-in webhook system with retry & delivery tracking |
| Multi-tenant headaches | Native organization & team scoping with JWT claims |
git clone https://github.com/mandarwagh9/MachineAuth.git
cd MachineAuth
go run ./cmd/serverServer starts on http://localhost:8080. No database needed — uses JSON file storage by default.
# 1. Create an agent
curl -s -X POST http://localhost:8080/api/agents \
-H "Content-Type: application/json" \
-d '{"name": "my-agent", "scopes": ["read", "write"]}' | jq .
# 2. Get a token
curl -s -X POST http://localhost:8080/oauth/token \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" | jq .
# 3. Use the token
curl -s -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
http://localhost:8080/api/agents/me | jq .Live demo: https://auth.writesomething.fun
- OAuth 2.0 Client Credentials — Industry-standard M2M authentication flow
- RS256 JWT Tokens — Asymmetric signing with auto-generated RSA keys
- Token Introspection — Validate tokens via RFC 7662 compliant endpoint
- Token Revocation — Invalidate tokens instantly via RFC 7009
- Refresh Tokens — Renew access without re-authenticating
- JWKS Endpoint — Public key discovery at
/.well-known/jwks.json
- Full CRUD — Create, list, view, update, delete agents
- Credential Rotation — Rotate client secrets with zero downtime
- Scoped Access — Fine-grained scopes per agent
- Usage Tracking — Token count, refresh count, last activity per agent
- Agent Self-Service — Agents manage their own lifecycle via JWT auth
- Activation Control — Deactivate/reactivate agents without deletion
- Organizations — Isolated tenant environments with unique slugs
- Teams — Group agents under teams within organizations
- Org-Scoped Agents — Agents belong to orgs, JWT claims include
org_id/team_id - API Keys — Per-organization API key management
- Event Notifications — Real-time HTTP callbacks for agent/token events
- Delivery Tracking — Full delivery history with status, attempts, errors
- Automatic Retries — Exponential backoff with configurable retry count
- Webhook Testing — Send test payloads to verify endpoint connectivity
- Background Workers — Async delivery processing (configurable worker count)
- Health Checks —
/healthand/health/readyendpoints - Metrics — Token/agent/error statistics at
/metrics - Audit Logging — Track all agent and token operations
- CORS — Configurable cross-origin settings
- Graceful Shutdown — Clean shutdown on SIGINT/SIGTERM
- Zero-DB Mode — JSON file storage for development (no database needed)
MachineAuth ships with a full admin UI built with React 18 + TypeScript + Tailwind CSS.
| Page | Description |
|---|---|
| Dashboard | Real-time metrics, health status, system overview |
| Agents | Browse, search, filter agents; view details, rotate credentials |
| Agent Detail | Credentials, scopes, usage stats, rotation, deactivation |
| Organizations | Multi-tenant org management with teams and agents |
| Token Tools | Generate, introspect, and revoke tokens from the UI |
| Webhooks | Create, manage, test webhooks; view delivery history |
| Metrics | Detailed token issuance, refresh, revocation statistics |
cd web
npm install
npm run devOpen http://localhost:3000 — proxies API calls to the Go backend on port 8081.
Default credentials: admin@example.com / changeme
⚠️ ChangeADMIN_EMAILandADMIN_PASSWORDenv vars before deploying to production.
cd web
npm run build # Output in web/dist/
npm run start # Serve with built-in static server on port 3000| Method | Endpoint | Description |
|---|---|---|
POST |
/oauth/token |
Issue access + refresh token |
POST |
/oauth/introspect |
Validate and inspect a token |
POST |
/oauth/revoke |
Revoke an access token |
POST |
/oauth/refresh |
Refresh an access token |
GET |
/.well-known/jwks.json |
Public key set (JWKS) |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/agents |
List all agents |
POST |
/api/agents |
Create a new agent |
GET |
/api/agents/{id} |
Get agent details |
DELETE |
/api/agents/{id} |
Delete an agent |
POST |
/api/agents/{id}/rotate |
Rotate agent credentials |
POST |
/api/agents/{id}/deactivate |
Deactivate an agent |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/agents/me |
Get own profile |
GET |
/api/agents/me/usage |
Get own usage statistics |
POST |
/api/agents/me/rotate |
Rotate own credentials |
POST |
/api/agents/me/deactivate |
Deactivate own account |
POST |
/api/agents/me/reactivate |
Reactivate own account |
DELETE |
/api/agents/me/delete |
Delete own account |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/webhooks |
List webhooks |
POST |
/api/webhooks |
Create webhook |
GET |
/api/webhooks/{id} |
Get webhook details |
PUT |
/api/webhooks/{id} |
Update webhook |
DELETE |
/api/webhooks/{id} |
Delete webhook |
POST |
/api/webhooks/{id}/test |
Send test delivery |
GET |
/api/webhooks/{id}/deliveries |
Get delivery history |
GET |
/api/webhook-events |
List available event types |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/organizations |
List organizations |
POST |
/api/organizations |
Create organization |
GET |
/api/organizations/{id} |
Get organization |
PUT |
/api/organizations/{id} |
Update organization |
DELETE |
/api/organizations/{id} |
Delete organization |
GET |
/api/organizations/{id}/teams |
List teams |
POST |
/api/organizations/{id}/teams |
Create team |
GET |
/api/organizations/{id}/agents |
List org agents |
POST |
/api/organizations/{id}/agents |
Create org agent |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/organizations/{id}/api-keys |
List API keys |
POST |
/api/organizations/{id}/api-keys |
Create API key |
DELETE |
/api/organizations/{id}/api-keys/{key_id} |
Revoke API key |
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Service info + version |
GET |
/health |
Health check |
GET |
/health/ready |
Readiness check (includes agent count) |
GET |
/metrics |
Token/agent/error metrics |
POST |
/api/verify |
Verify JWT and return agent info |
curl -X POST http://localhost:8080/api/agents \
-H "Content-Type: application/json" \
-d '{"name": "my-agent", "scopes": ["read", "write"]}'{
"agent": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "my-agent",
"client_id": "cid_a1b2c3d4e5f6",
"scopes": ["read", "write"],
"is_active": true,
"created_at": "2026-03-01T12:00:00Z"
},
"client_secret": "cs_xK9mPqR...",
"message": "Save this client_secret - it will not be shown again!"
}
⚠️ Theclient_secretis only returned once. Store it securely.
curl -X POST http://localhost:8080/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=cid_a1b2c3d4e5f6" \
-d "client_secret=cs_xK9mPqR..."{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "rt_8f14e45f..."
}curl -X POST http://localhost:8080/oauth/introspect \
-d "token=eyJhbGciOiJSUzI1NiIs..."{
"active": true,
"client_id": "cid_a1b2c3d4e5f6",
"scope": "read write",
"token_type": "Bearer",
"exp": 1709308800,
"iat": 1709305200
}curl -X POST http://localhost:8080/oauth/refresh \
-d "refresh_token=rt_8f14e45f..." \
-d "client_id=cid_a1b2c3d4e5f6" \
-d "client_secret=cs_xK9mPqR..."curl -X POST http://localhost:8080/oauth/revoke \
-d "token=eyJhbGciOiJSUzI1NiIs..."curl -X POST http://localhost:8080/api/agents/{agent_id}/rotateReturns a new client_secret — the old one is immediately invalidated.
Agents can manage themselves using their JWT token:
# View own profile
curl -H "Authorization: Bearer eyJ..." http://localhost:8080/api/agents/me
# Check usage stats
curl -H "Authorization: Bearer eyJ..." http://localhost:8080/api/agents/me/usage
# Rotate own credentials
curl -X POST -H "Authorization: Bearer eyJ..." http://localhost:8080/api/agents/me/rotate
# Deactivate own account
curl -X POST -H "Authorization: Bearer eyJ..." http://localhost:8080/api/agents/me/deactivate
# Delete own account permanently
curl -X DELETE -H "Authorization: Bearer eyJ..." http://localhost:8080/api/agents/me/delete# Create a webhook
curl -X POST http://localhost:8080/api/webhooks \
-H "Content-Type: application/json" \
-d '{
"name": "Prod Notifications",
"url": "https://example.com/webhooks",
"events": ["agent.created", "agent.deleted", "token.issued"],
"max_retries": 5
}'
# Test it
curl -X POST http://localhost:8080/api/webhooks/{id}/test \
-H "Content-Type: application/json" \
-d '{"event": "webhook.test"}'
# Check delivery history
curl http://localhost:8080/api/webhooks/{id}/deliveries# Create an organization
curl -X POST http://localhost:8080/api/organizations \
-H "Content-Type: application/json" \
-d '{"name": "Acme Corp", "slug": "acme", "owner_email": "admin@acme.com"}'
# Create a team
curl -X POST http://localhost:8080/api/organizations/{org_id}/teams \
-H "Content-Type: application/json" \
-d '{"name": "Engineering", "description": "Engineering team"}'
# Create an API key
curl -X POST http://localhost:8080/api/organizations/{org_id}/api-keys \
-H "Content-Type: application/json" \
-d '{"name": "production-key", "expires_in": 86400}'API keys can be used in place of JWT tokens:
curl -H "Authorization: Bearer sk_1cF4CG1RE..." http://localhost:8080/api/verifyTokens issued by MachineAuth include rich claims for authorization decisions:
{
"iss": "https://auth.yourdomain.com",
"sub": "cid_a1b2c3d4e5f6",
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"org_id": "org-uuid",
"team_id": "team-uuid",
"scope": ["read", "write"],
"jti": "unique-token-id",
"exp": 1709308800,
"iat": 1709305200
}Validate tokens using the public key from /.well-known/jwks.json.
Official client libraries for TypeScript and Python.
npm install @machineauth/sdkimport { MachineAuthClient } from '@machineauth/sdk'
const client = new MachineAuthClient({
baseUrl: 'https://auth.yourdomain.com',
clientId: 'cid_a1b2c3d4e5f6',
clientSecret: 'cs_xK9mPqR...',
})
// Get a token
const token = await client.getToken({ scope: 'read write' })
// List agents
const agents = await client.listAgents()
// Self-service
const me = await client.getMe()pip install machineauthfrom machineauth import MachineAuthClient
client = MachineAuthClient(
base_url="https://auth.yourdomain.com",
client_id="cid_a1b2c3d4e5f6",
client_secret="cs_xK9mPqR...",
)
# Get a token
token = client.get_token(scope="read write")
# Async support
from machineauth import AsyncMachineAuthClient
async_client = AsyncMachineAuthClient(...)
token = await async_client.get_token(scope="read write")See sdk/README.md for the full SDK documentation.
All configuration via environment variables (or .env file):
| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
Server listen port |
ENV |
development |
Environment (development / production) |
DATABASE_URL |
json:machineauth.json |
Database connection string |
JWT_SIGNING_ALGORITHM |
RS256 |
JWT signing algorithm |
JWT_KEY_ID |
key-1 |
JWKS key identifier |
JWT_ACCESS_TOKEN_EXPIRY |
3600 |
Access token TTL in seconds (1 hour) |
ALLOWED_ORIGINS |
http://localhost:3000 |
CORS allowed origins (comma-separated) |
REQUIRE_HTTPS |
false |
Enforce HTTPS redirects |
ADMIN_EMAIL |
admin@example.com |
Admin dashboard email |
ADMIN_PASSWORD |
changeme |
Admin dashboard password |
WEBHOOK_WORKER_COUNT |
3 |
Concurrent webhook delivery workers |
WEBHOOK_MAX_RETRIES |
10 |
Max delivery retry attempts |
WEBHOOK_TIMEOUT_SECS |
10 |
Webhook HTTP request timeout |
# JSON file (default, zero deps, great for dev)
DATABASE_URL=json:machineauth.json
# PostgreSQL (recommended for production)
DATABASE_URL=postgresql://user:pass@localhost:5432/machineauthPORT=8080
ENV=production
DATABASE_URL=postgresql://machineauth:secret@db:5432/machineauth
JWT_ACCESS_TOKEN_EXPIRY=1800
ALLOWED_ORIGINS=https://dashboard.yourdomain.com
ADMIN_PASSWORD=your-secure-password
WEBHOOK_WORKER_COUNT=5git clone https://github.com/mandarwagh9/MachineAuth.git
cd MachineAuth
docker-compose up -dThis starts three services:
| Service | Port | Description |
|---|---|---|
| postgres | 5432 | PostgreSQL 15 database |
| server | 8080 | Go API server |
| web | 80 | React admin dashboard |
# docker/Dockerfile.server — Multi-stage build
FROM golang:1.21-alpine AS builder
# ... builds to /server
FROM alpine:3.19
COPY --from=builder /server .
EXPOSE 8080
CMD ["./server"]docker build -f docker/Dockerfile.server -t machineauth .
docker run -p 8080:8080 -e DATABASE_URL=json:/data/machineauth.json machineauth# Requirements: Go 1.21+
go build -o machineauth ./cmd/server
./machineauth[Unit]
Description=MachineAuth - OAuth 2.0 for AI Agents
After=network.target
[Service]
Type=simple
User=machineauth
WorkingDirectory=/opt/machineauth
ExecStart=/opt/machineauth/machineauth
EnvironmentFile=/opt/machineauth/.env
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetsudo systemctl enable machineauth
sudo systemctl start machineauth┌─────────────────┐ ┌──────────────┐ ┌──────────────┐
│ React Admin UI │────▶│ Go Server │────▶│ PostgreSQL │
│ (Tailwind CSS) │ │ (net/http) │ │ or JSON file │
└─────────────────┘ └──────┬───────┘ └──────────────┘
│
┌──────────┼──────────┐
│ │ │
┌─────▼──┐ ┌────▼───┐ ┌────▼────┐
│ Agents │ │ Tokens │ │Webhooks │
│ Service │ │Service │ │ Worker │
└────────┘ └────────┘ └─────────┘
machineauth/
├── cmd/server/main.go # Server entry point
├── internal/
│ ├── config/config.go # Environment configuration
│ ├── db/db.go # Database layer (Postgres + JSON)
│ ├── handlers/ # HTTP request handlers
│ │ ├── agents.go # Agent CRUD + self-service
│ │ ├── auth.go # OAuth2 token endpoints
│ │ └── webhook.go # Webhook management
│ ├── middleware/ # Logging, CORS
│ ├── models/models.go # All data types and DTOs
│ ├── services/ # Business logic
│ │ ├── agent.go # Agent operations
│ │ ├── audit.go # Audit logging + webhook triggers
│ │ ├── token.go # JWT creation/validation
│ │ ├── webhook.go # Webhook CRUD
│ │ └── webhook_worker.go # Async delivery processing
│ └── utils/crypto.go # Cryptographic helpers
├── web/ # React admin dashboard
│ ├── src/
│ │ ├── pages/ # Dashboard, Agents, Tokens, Webhooks, etc.
│ │ ├── components/ # Layout, Sidebar
│ │ ├── services/ # API client (axios)
│ │ └── types/ # TypeScript interfaces
│ └── vite.config.ts # Vite + proxy config
├── sdk/
│ ├── typescript/ # @machineauth/sdk (npm)
│ └── python/ # machineauth (pip)
├── docker/ # Dockerfiles
├── deploy/ # Deployment scripts
└── docker-compose.yml # Full-stack compose
- Use HTTPS — Always run behind a TLS-terminating reverse proxy in production
- Rotate credentials — Use the rotation API regularly; old secrets are invalidated immediately
- Short token expiry — Default 1 hour; reduce to 15-30 min for sensitive workloads
- Restrict CORS — Set
ALLOWED_ORIGINSto your specific domains - Change admin password — Default is
changeme; setADMIN_PASSWORDbefore deploying - Monitor metrics — Watch
/metricsfor token issuance anomalies - Use Postgres in prod — JSON file storage is for development only
Please email security concerns directly rather than opening public issues. See SECURITY.md.
| Component | Technology |
|---|---|
| Backend | Go 1.21, net/http, golang-jwt/jwt/v5 |
| Frontend | React 18, TypeScript 5.3, Vite 5, Tailwind CSS 3.4 |
| Database | PostgreSQL 15 (prod) / JSON file (dev) |
| Auth | OAuth 2.0 Client Credentials, RS256 JWT |
| Icons | Lucide React |
| Toasts | Sonner |
| HTTP Client | Axios |
Contributions are welcome!
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing) - Make your changes and add tests
- Run
go test -v ./...andcd web && npm run build - Commit (
git commit -m 'feat: add amazing feature') - Push (
git push origin feature/amazing) - Open a Pull Request
See CONTRIBUTING.md for detailed guidelines.
MIT License — see LICENSE for details.
- Live Demo: https://auth.writesomething.fun
- Issues: GitHub Issues
- SDK Docs: sdk/README.md
Built for the AI agent ecosystem 🤖