authgent-server 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- authgent_server-0.1.0/.env.example +59 -0
- authgent_server-0.1.0/.gitignore +17 -0
- authgent_server-0.1.0/Dockerfile +23 -0
- authgent_server-0.1.0/PKG-INFO +258 -0
- authgent_server-0.1.0/README.md +205 -0
- authgent_server-0.1.0/authgent_server/__init__.py +3 -0
- authgent_server-0.1.0/authgent_server/app.py +155 -0
- authgent_server-0.1.0/authgent_server/cli.py +1103 -0
- authgent_server-0.1.0/authgent_server/config.py +128 -0
- authgent_server-0.1.0/authgent_server/crypto.py +33 -0
- authgent_server-0.1.0/authgent_server/db.py +81 -0
- authgent_server-0.1.0/authgent_server/dependencies.py +210 -0
- authgent_server-0.1.0/authgent_server/endpoints/__init__.py +32 -0
- authgent_server-0.1.0/authgent_server/endpoints/agents.py +88 -0
- authgent_server-0.1.0/authgent_server/endpoints/audit.py +95 -0
- authgent_server-0.1.0/authgent_server/endpoints/authorize.py +204 -0
- authgent_server-0.1.0/authgent_server/endpoints/device.py +204 -0
- authgent_server-0.1.0/authgent_server/endpoints/health.py +51 -0
- authgent_server-0.1.0/authgent_server/endpoints/introspect.py +49 -0
- authgent_server-0.1.0/authgent_server/endpoints/register.py +22 -0
- authgent_server-0.1.0/authgent_server/endpoints/revoke.py +33 -0
- authgent_server-0.1.0/authgent_server/endpoints/stepup.py +97 -0
- authgent_server-0.1.0/authgent_server/endpoints/token.py +120 -0
- authgent_server-0.1.0/authgent_server/endpoints/token_check.py +151 -0
- authgent_server-0.1.0/authgent_server/endpoints/token_inspect.py +134 -0
- authgent_server-0.1.0/authgent_server/endpoints/wellknown.py +107 -0
- authgent_server-0.1.0/authgent_server/errors.py +138 -0
- authgent_server-0.1.0/authgent_server/logging.py +107 -0
- authgent_server-0.1.0/authgent_server/middleware/__init__.py +1 -0
- authgent_server-0.1.0/authgent_server/middleware/cors.py +23 -0
- authgent_server-0.1.0/authgent_server/middleware/error_handler.py +77 -0
- authgent_server-0.1.0/authgent_server/middleware/rate_limit.py +76 -0
- authgent_server-0.1.0/authgent_server/middleware/request_id.py +38 -0
- authgent_server-0.1.0/authgent_server/models/__init__.py +33 -0
- authgent_server-0.1.0/authgent_server/models/agent.py +39 -0
- authgent_server-0.1.0/authgent_server/models/audit_log.py +22 -0
- authgent_server-0.1.0/authgent_server/models/authorization_code.py +26 -0
- authgent_server-0.1.0/authgent_server/models/base.py +29 -0
- authgent_server-0.1.0/authgent_server/models/consent.py +29 -0
- authgent_server-0.1.0/authgent_server/models/delegation_receipt.py +19 -0
- authgent_server-0.1.0/authgent_server/models/device_code.py +25 -0
- authgent_server-0.1.0/authgent_server/models/oauth_client.py +35 -0
- authgent_server-0.1.0/authgent_server/models/refresh_token.py +25 -0
- authgent_server-0.1.0/authgent_server/models/signing_key.py +20 -0
- authgent_server-0.1.0/authgent_server/models/stepup_request.py +24 -0
- authgent_server-0.1.0/authgent_server/models/token_blocklist.py +17 -0
- authgent_server-0.1.0/authgent_server/models/user.py +19 -0
- authgent_server-0.1.0/authgent_server/providers/__init__.py +1 -0
- authgent_server-0.1.0/authgent_server/providers/attestation.py +15 -0
- authgent_server-0.1.0/authgent_server/providers/events.py +60 -0
- authgent_server-0.1.0/authgent_server/providers/hitl.py +167 -0
- authgent_server-0.1.0/authgent_server/providers/keys.py +15 -0
- authgent_server-0.1.0/authgent_server/providers/policy.py +17 -0
- authgent_server-0.1.0/authgent_server/providers/protocols.py +116 -0
- authgent_server-0.1.0/authgent_server/schemas/__init__.py +1 -0
- authgent_server-0.1.0/authgent_server/schemas/agent.py +65 -0
- authgent_server-0.1.0/authgent_server/schemas/client.py +73 -0
- authgent_server-0.1.0/authgent_server/schemas/common.py +42 -0
- authgent_server-0.1.0/authgent_server/schemas/token.py +36 -0
- authgent_server-0.1.0/authgent_server/services/__init__.py +1 -0
- authgent_server-0.1.0/authgent_server/services/agent_service.py +166 -0
- authgent_server-0.1.0/authgent_server/services/audit_service.py +47 -0
- authgent_server-0.1.0/authgent_server/services/client_service.py +162 -0
- authgent_server-0.1.0/authgent_server/services/consent_service.py +60 -0
- authgent_server-0.1.0/authgent_server/services/delegation_service.py +152 -0
- authgent_server-0.1.0/authgent_server/services/dpop_service.py +156 -0
- authgent_server-0.1.0/authgent_server/services/external_oidc.py +220 -0
- authgent_server-0.1.0/authgent_server/services/jwks_service.py +204 -0
- authgent_server-0.1.0/authgent_server/services/stepup_service.py +90 -0
- authgent_server-0.1.0/authgent_server/services/token_service.py +647 -0
- authgent_server-0.1.0/authgent_server/templates/consent.html +88 -0
- authgent_server-0.1.0/authgent_server/utils.py +22 -0
- authgent_server-0.1.0/docker-compose.yml +33 -0
- authgent_server-0.1.0/migrations/alembic.ini +36 -0
- authgent_server-0.1.0/migrations/env.py +60 -0
- authgent_server-0.1.0/migrations/versions/.gitkeep +0 -0
- authgent_server-0.1.0/migrations/versions/001_initial_schema.py +233 -0
- authgent_server-0.1.0/pyproject.toml +102 -0
- authgent_server-0.1.0/tests/__init__.py +0 -0
- authgent_server-0.1.0/tests/agent_to_agent_simulation.py +1426 -0
- authgent_server-0.1.0/tests/conftest.py +71 -0
- authgent_server-0.1.0/tests/simulation_test.py +846 -0
- authgent_server-0.1.0/tests/test_agents.py +284 -0
- authgent_server-0.1.0/tests/test_audit_endpoint.py +188 -0
- authgent_server-0.1.0/tests/test_authorize.py +110 -0
- authgent_server-0.1.0/tests/test_cli_phase0.py +335 -0
- authgent_server-0.1.0/tests/test_crypto.py +116 -0
- authgent_server-0.1.0/tests/test_delegation.py +212 -0
- authgent_server-0.1.0/tests/test_device.py +154 -0
- authgent_server-0.1.0/tests/test_dpop.py +302 -0
- authgent_server-0.1.0/tests/test_dpop_integration.py +416 -0
- authgent_server-0.1.0/tests/test_error_handler.py +58 -0
- authgent_server-0.1.0/tests/test_external_oidc.py +723 -0
- authgent_server-0.1.0/tests/test_health.py +18 -0
- authgent_server-0.1.0/tests/test_hitl_provider.py +53 -0
- authgent_server-0.1.0/tests/test_integration_workflows.py +1533 -0
- authgent_server-0.1.0/tests/test_introspect.py +91 -0
- authgent_server-0.1.0/tests/test_log_redaction.py +122 -0
- authgent_server-0.1.0/tests/test_real_world_agents.py +1395 -0
- authgent_server-0.1.0/tests/test_register.py +60 -0
- authgent_server-0.1.0/tests/test_registration_policy.py +134 -0
- authgent_server-0.1.0/tests/test_revoke.py +54 -0
- authgent_server-0.1.0/tests/test_security.py +464 -0
- authgent_server-0.1.0/tests/test_stepup.py +106 -0
- authgent_server-0.1.0/tests/test_token.py +94 -0
- authgent_server-0.1.0/tests/test_token_advanced.py +412 -0
- authgent_server-0.1.0/tests/test_token_check.py +152 -0
- authgent_server-0.1.0/tests/test_token_expiry.py +103 -0
- authgent_server-0.1.0/tests/test_token_inspect.py +226 -0
- authgent_server-0.1.0/tests/test_wellknown.py +95 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# authgent-server configuration
|
|
2
|
+
# Copy to .env and customize
|
|
3
|
+
|
|
4
|
+
# Required: Master secret key (run `authgent-server init` to generate)
|
|
5
|
+
AUTHGENT_SECRET_KEY=
|
|
6
|
+
|
|
7
|
+
# Database (SQLite for dev, PostgreSQL for prod)
|
|
8
|
+
AUTHGENT_DATABASE_URL=sqlite+aiosqlite:///./authgent.db
|
|
9
|
+
# AUTHGENT_DATABASE_URL=postgresql+asyncpg://authgent:authgent@localhost:5432/authgent
|
|
10
|
+
|
|
11
|
+
# Server
|
|
12
|
+
AUTHGENT_HOST=0.0.0.0
|
|
13
|
+
AUTHGENT_PORT=8000
|
|
14
|
+
AUTHGENT_SERVER_URL=http://localhost:8000
|
|
15
|
+
AUTHGENT_DEBUG=false
|
|
16
|
+
|
|
17
|
+
# Token TTLs (seconds)
|
|
18
|
+
AUTHGENT_ACCESS_TOKEN_TTL=900
|
|
19
|
+
AUTHGENT_REFRESH_TOKEN_TTL=86400
|
|
20
|
+
AUTHGENT_EXCHANGE_TOKEN_TTL=300
|
|
21
|
+
|
|
22
|
+
# Policy
|
|
23
|
+
AUTHGENT_REGISTRATION_POLICY=open
|
|
24
|
+
AUTHGENT_CONSENT_MODE=auto_approve
|
|
25
|
+
AUTHGENT_MAX_DELEGATION_DEPTH=5
|
|
26
|
+
AUTHGENT_DELEGATION_SCOPE_REDUCTION=true
|
|
27
|
+
AUTHGENT_RESOURCE_MATCH=exact
|
|
28
|
+
|
|
29
|
+
# DPoP
|
|
30
|
+
AUTHGENT_REQUIRE_DPOP=false
|
|
31
|
+
AUTHGENT_DPOP_CHAIN_POLICY=strict
|
|
32
|
+
|
|
33
|
+
# HITL / Step-Up
|
|
34
|
+
AUTHGENT_HITL_TIMEOUT=300
|
|
35
|
+
# AUTHGENT_HITL_SCOPES=["bank:transfer","admin:delete"]
|
|
36
|
+
|
|
37
|
+
# Human auth mode: builtin | external_oidc | api_key
|
|
38
|
+
AUTHGENT_HUMAN_AUTH_MODE=builtin
|
|
39
|
+
|
|
40
|
+
# External OIDC trust for id_token exchange (§4.7)
|
|
41
|
+
# Comma-separated issuer URLs for Auth0/Clerk/Okta
|
|
42
|
+
# AUTHGENT_TRUSTED_OIDC_ISSUERS=["https://dev-abc123.us.auth0.com/","https://clerk.example.com"]
|
|
43
|
+
# Expected 'aud' claim in external id_tokens (your app's client_id at the IdP)
|
|
44
|
+
# AUTHGENT_TRUSTED_OIDC_AUDIENCE=your-app-client-id
|
|
45
|
+
|
|
46
|
+
# CORS (JSON array of origins, empty = allow all)
|
|
47
|
+
AUTHGENT_CORS_ORIGINS=[]
|
|
48
|
+
|
|
49
|
+
# Rate limiting
|
|
50
|
+
AUTHGENT_TOKEN_RATE_LIMIT=100
|
|
51
|
+
AUTHGENT_REGISTER_RATE_LIMIT=10
|
|
52
|
+
|
|
53
|
+
# Pluggable providers (dotted import paths, leave empty for defaults)
|
|
54
|
+
# AUTHGENT_ATTESTATION_PROVIDER=
|
|
55
|
+
# AUTHGENT_POLICY_PROVIDER=
|
|
56
|
+
# AUTHGENT_HITL_PROVIDER=
|
|
57
|
+
# AUTHGENT_KEY_PROVIDER=
|
|
58
|
+
# AUTHGENT_EVENT_EMITTER=
|
|
59
|
+
# AUTHGENT_CLAIM_ENRICHER=
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
|
|
5
|
+
# Install dependencies first (layer caching)
|
|
6
|
+
COPY pyproject.toml README.md ./
|
|
7
|
+
COPY authgent_server/__init__.py authgent_server/__init__.py
|
|
8
|
+
RUN pip install --no-cache-dir .[postgres]
|
|
9
|
+
|
|
10
|
+
# Copy full source
|
|
11
|
+
COPY authgent_server/ authgent_server/
|
|
12
|
+
|
|
13
|
+
# Non-root user for security
|
|
14
|
+
RUN addgroup --system authgent && adduser --system --ingroup authgent authgent \
|
|
15
|
+
&& chown -R authgent:authgent /app
|
|
16
|
+
USER authgent
|
|
17
|
+
|
|
18
|
+
EXPOSE 8000
|
|
19
|
+
|
|
20
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
21
|
+
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
|
|
22
|
+
|
|
23
|
+
CMD ["uvicorn", "authgent_server.app:create_app", "--factory", "--host", "0.0.0.0", "--port", "8000"]
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: authgent-server
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The open-source identity provider for AI agents — OAuth 2.1 Authorization Server
|
|
5
|
+
Project-URL: Homepage, https://github.com/authgent/authgent
|
|
6
|
+
Project-URL: Documentation, https://github.com/authgent/authgent/tree/main/server
|
|
7
|
+
Project-URL: Repository, https://github.com/authgent/authgent
|
|
8
|
+
Project-URL: Changelog, https://github.com/authgent/authgent/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Issues, https://github.com/authgent/authgent/issues
|
|
10
|
+
Author: Dhruv Agnihotri
|
|
11
|
+
License-Expression: Apache-2.0
|
|
12
|
+
Keywords: a2a,agent,ai-agent,auth,delegation,dpop,identity,mcp,oauth
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Framework :: FastAPI
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Security
|
|
21
|
+
Classifier: Topic :: System :: Systems Administration :: Authentication/Directory
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Requires-Dist: aiosqlite>=0.20.0
|
|
24
|
+
Requires-Dist: bcrypt>=4.2.0
|
|
25
|
+
Requires-Dist: cryptography>=43.0.0
|
|
26
|
+
Requires-Dist: fastapi>=0.115.0
|
|
27
|
+
Requires-Dist: httpx>=0.27.0
|
|
28
|
+
Requires-Dist: jinja2>=3.1.0
|
|
29
|
+
Requires-Dist: pydantic-settings>=2.5.0
|
|
30
|
+
Requires-Dist: pydantic>=2.9.0
|
|
31
|
+
Requires-Dist: pyjwt>=2.9.0
|
|
32
|
+
Requires-Dist: python-multipart>=0.0.9
|
|
33
|
+
Requires-Dist: python-ulid>=2.7.0
|
|
34
|
+
Requires-Dist: rich>=13.7.0
|
|
35
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0.30
|
|
36
|
+
Requires-Dist: structlog>=24.4.0
|
|
37
|
+
Requires-Dist: typer>=0.12.0
|
|
38
|
+
Requires-Dist: uvicorn[standard]>=0.30.0
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: coverage>=7.6.0; extra == 'dev'
|
|
41
|
+
Requires-Dist: freezegun>=1.4.0; extra == 'dev'
|
|
42
|
+
Requires-Dist: httpx>=0.27.0; extra == 'dev'
|
|
43
|
+
Requires-Dist: mypy>=1.11.0; extra == 'dev'
|
|
44
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
|
|
45
|
+
Requires-Dist: pytest>=8.3.0; extra == 'dev'
|
|
46
|
+
Requires-Dist: ruff>=0.6.0; extra == 'dev'
|
|
47
|
+
Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
|
|
48
|
+
Provides-Extra: migrations
|
|
49
|
+
Requires-Dist: alembic>=1.13.0; extra == 'migrations'
|
|
50
|
+
Provides-Extra: postgres
|
|
51
|
+
Requires-Dist: asyncpg>=0.30.0; extra == 'postgres'
|
|
52
|
+
Description-Content-Type: text/markdown
|
|
53
|
+
|
|
54
|
+
# authgent-server
|
|
55
|
+
|
|
56
|
+
The open-source OAuth 2.1 Authorization Server for AI agents — MCP-native, delegation-aware, with DPoP sender-constrained tokens and human-in-the-loop step-up authorization.
|
|
57
|
+
|
|
58
|
+
[](https://pypi.org/project/authgent-server/)
|
|
59
|
+
[](https://python.org)
|
|
60
|
+
[](../LICENSE)
|
|
61
|
+
|
|
62
|
+
## Install
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install authgent-server
|
|
66
|
+
|
|
67
|
+
# With PostgreSQL support
|
|
68
|
+
pip install authgent-server[postgres]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Initialize (generates secret key, creates DB, generates signing key)
|
|
75
|
+
authgent-server init
|
|
76
|
+
|
|
77
|
+
# Start the server
|
|
78
|
+
authgent-server run
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Server starts at `http://localhost:8000`:
|
|
82
|
+
- `GET /.well-known/oauth-authorization-server` — server metadata
|
|
83
|
+
- `GET /.well-known/jwks.json` — public signing keys
|
|
84
|
+
- `GET /docs` — interactive Swagger UI
|
|
85
|
+
|
|
86
|
+
## CLI Commands
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
authgent-server init # Generate .env, create DB, signing key
|
|
90
|
+
authgent-server run # Start server (uvicorn)
|
|
91
|
+
authgent-server create-agent # Register an agent interactively
|
|
92
|
+
authgent-server migrate # Run Alembic migrations
|
|
93
|
+
authgent-server migrate --dry-run # Preview pending migrations
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## API Endpoints
|
|
97
|
+
|
|
98
|
+
### OAuth 2.1 Core
|
|
99
|
+
|
|
100
|
+
| Method | Path | Description |
|
|
101
|
+
|:-------|:-----|:------------|
|
|
102
|
+
| `POST` | `/register` | Dynamic client registration (RFC 7591) |
|
|
103
|
+
| `POST` | `/token` | Token endpoint — all grant types |
|
|
104
|
+
| `GET` | `/authorize` | Authorization code + PKCE (consent page) |
|
|
105
|
+
| `POST` | `/authorize` | Authorization code (consent submission) |
|
|
106
|
+
| `POST` | `/introspect` | Token introspection (RFC 7662) |
|
|
107
|
+
| `POST` | `/revoke` | Token revocation (RFC 7009) |
|
|
108
|
+
|
|
109
|
+
### Device Authorization (RFC 8628)
|
|
110
|
+
|
|
111
|
+
| Method | Path | Description |
|
|
112
|
+
|:-------|:-----|:------------|
|
|
113
|
+
| `POST` | `/device/authorize` | Request device + user codes |
|
|
114
|
+
| `POST` | `/device/approve` | Human approves device code |
|
|
115
|
+
| `POST` | `/device/deny` | Human denies device code |
|
|
116
|
+
|
|
117
|
+
### Step-Up Authorization (HITL)
|
|
118
|
+
|
|
119
|
+
| Method | Path | Description |
|
|
120
|
+
|:-------|:-----|:------------|
|
|
121
|
+
| `POST` | `/stepup` | Create step-up request |
|
|
122
|
+
| `GET` | `/stepup/{id}` | Poll step-up status |
|
|
123
|
+
| `POST` | `/stepup/{id}/approve` | Human approves |
|
|
124
|
+
| `POST` | `/stepup/{id}/deny` | Human denies |
|
|
125
|
+
|
|
126
|
+
### Agent Identity Registry
|
|
127
|
+
|
|
128
|
+
| Method | Path | Description |
|
|
129
|
+
|:-------|:-----|:------------|
|
|
130
|
+
| `POST` | `/agents` | Register agent (auto-creates OAuth client) |
|
|
131
|
+
| `GET` | `/agents` | List agents (paginated, filterable) |
|
|
132
|
+
| `GET` | `/agents/{id}` | Get agent details |
|
|
133
|
+
| `PATCH` | `/agents/{id}` | Update agent |
|
|
134
|
+
| `DELETE` | `/agents/{id}` | Deactivate agent |
|
|
135
|
+
|
|
136
|
+
### Discovery & Health
|
|
137
|
+
|
|
138
|
+
| Method | Path | Description |
|
|
139
|
+
|:-------|:-----|:------------|
|
|
140
|
+
| `GET` | `/.well-known/oauth-authorization-server` | Server metadata (RFC 8414) |
|
|
141
|
+
| `GET` | `/.well-known/openid-configuration` | OIDC-compatible alias |
|
|
142
|
+
| `GET` | `/.well-known/jwks.json` | Public signing keys |
|
|
143
|
+
| `GET` | `/.well-known/oauth-protected-resource` | Resource metadata (RFC 9728) |
|
|
144
|
+
| `GET` | `/health` | Liveness check |
|
|
145
|
+
| `GET` | `/ready` | Readiness (DB + signing keys) |
|
|
146
|
+
|
|
147
|
+
## Configuration
|
|
148
|
+
|
|
149
|
+
All settings via `AUTHGENT_*` environment variables. See [`.env.example`](.env.example) for the full list.
|
|
150
|
+
|
|
151
|
+
### Essential
|
|
152
|
+
|
|
153
|
+
| Variable | Default | Description |
|
|
154
|
+
|:---------|:--------|:------------|
|
|
155
|
+
| `AUTHGENT_SECRET_KEY` | *generated* | Master secret for HKDF key derivation |
|
|
156
|
+
| `AUTHGENT_DATABASE_URL` | `sqlite+aiosqlite:///./authgent.db` | Database URL |
|
|
157
|
+
| `AUTHGENT_HOST` | `0.0.0.0` | Bind address |
|
|
158
|
+
| `AUTHGENT_PORT` | `8000` | Bind port |
|
|
159
|
+
|
|
160
|
+
### Token Lifetimes
|
|
161
|
+
|
|
162
|
+
| Variable | Default | Description |
|
|
163
|
+
|:---------|:--------|:------------|
|
|
164
|
+
| `AUTHGENT_ACCESS_TOKEN_TTL` | `900` | Access token (15 min) |
|
|
165
|
+
| `AUTHGENT_REFRESH_TOKEN_TTL` | `86400` | Refresh token (24 hr) |
|
|
166
|
+
| `AUTHGENT_EXCHANGE_TOKEN_TTL` | `300` | Exchanged token (5 min) |
|
|
167
|
+
|
|
168
|
+
### Policy
|
|
169
|
+
|
|
170
|
+
| Variable | Default | Description |
|
|
171
|
+
|:---------|:--------|:------------|
|
|
172
|
+
| `AUTHGENT_MAX_DELEGATION_DEPTH` | `5` | Max delegation chain hops |
|
|
173
|
+
| `AUTHGENT_REQUIRE_DPOP` | `false` | Require DPoP on all token requests |
|
|
174
|
+
| `AUTHGENT_CONSENT_MODE` | `auto_approve` | `auto_approve`, `ui`, `headless` |
|
|
175
|
+
| `AUTHGENT_REGISTRATION_POLICY` | `open` | `open`, `token`, `admin` |
|
|
176
|
+
|
|
177
|
+
### Pluggable Providers
|
|
178
|
+
|
|
179
|
+
| Variable | Default | Description |
|
|
180
|
+
|:---------|:--------|:------------|
|
|
181
|
+
| `AUTHGENT_ATTESTATION_PROVIDER` | *null* | Dotted import path |
|
|
182
|
+
| `AUTHGENT_POLICY_PROVIDER` | *null* | Custom policy enforcement |
|
|
183
|
+
| `AUTHGENT_HITL_PROVIDER` | *webhook* | Step-up notification backend |
|
|
184
|
+
| `AUTHGENT_KEY_PROVIDER` | *database* | Signing key storage |
|
|
185
|
+
| `AUTHGENT_EVENT_EMITTER` | *database* | Audit event backend |
|
|
186
|
+
| `AUTHGENT_CLAIM_ENRICHER` | *null* | Custom token claim enrichment |
|
|
187
|
+
|
|
188
|
+
## Deployment
|
|
189
|
+
|
|
190
|
+
### Docker
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
docker compose up -d
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The included [`docker-compose.yml`](docker-compose.yml) runs the server with PostgreSQL.
|
|
197
|
+
|
|
198
|
+
### Docker (standalone)
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
docker build -t authgent-server .
|
|
202
|
+
docker run -p 8000:8000 \
|
|
203
|
+
-e AUTHGENT_SECRET_KEY=your-secret-key \
|
|
204
|
+
-e AUTHGENT_DATABASE_URL=sqlite+aiosqlite:///./authgent.db \
|
|
205
|
+
authgent-server
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Production Checklist
|
|
209
|
+
|
|
210
|
+
- [ ] Set a strong `AUTHGENT_SECRET_KEY` (64+ characters)
|
|
211
|
+
- [ ] Use PostgreSQL (`AUTHGENT_DATABASE_URL=postgresql+asyncpg://...`)
|
|
212
|
+
- [ ] Run migrations: `authgent-server migrate`
|
|
213
|
+
- [ ] Set `AUTHGENT_REGISTRATION_POLICY=token` or `admin`
|
|
214
|
+
- [ ] Set `AUTHGENT_CONSENT_MODE=ui` for human-facing flows
|
|
215
|
+
- [ ] Enable DPoP: `AUTHGENT_REQUIRE_DPOP=true`
|
|
216
|
+
- [ ] Configure CORS origins: `AUTHGENT_CORS_ORIGINS=["https://your-app.com"]`
|
|
217
|
+
- [ ] Put behind a reverse proxy (nginx/Caddy) with TLS
|
|
218
|
+
- [ ] Set up log aggregation (structured JSON output)
|
|
219
|
+
|
|
220
|
+
## Architecture
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
Endpoints → Services → Models → DB
|
|
224
|
+
(thin) (stateless) (ORM) (async)
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
- **Endpoints** — FastAPI routers, HTTP validation, dependency injection
|
|
228
|
+
- **Services** — All business logic, receive `db: AsyncSession` per call
|
|
229
|
+
- **Models** — SQLAlchemy 2.0 async ORM, 9 tables
|
|
230
|
+
- **Providers** — 7 pluggable Python Protocol interfaces (attestation, policy, HITL, keys, events, claim enricher, human auth)
|
|
231
|
+
|
|
232
|
+
See [ARCHITECTURE.md](../ARCHITECTURE.md) for the full implementation design.
|
|
233
|
+
|
|
234
|
+
## Development
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Setup
|
|
238
|
+
git clone https://github.com/authgent/authgent.git
|
|
239
|
+
cd authgent/server
|
|
240
|
+
pip install -e ".[dev,migrations]"
|
|
241
|
+
authgent-server init
|
|
242
|
+
|
|
243
|
+
# Test (192 tests)
|
|
244
|
+
pytest -v
|
|
245
|
+
|
|
246
|
+
# Lint + format
|
|
247
|
+
ruff check . && ruff format --check .
|
|
248
|
+
|
|
249
|
+
# Type check
|
|
250
|
+
mypy authgent_server/ --ignore-missing-imports
|
|
251
|
+
|
|
252
|
+
# Coverage
|
|
253
|
+
coverage run -m pytest tests/ && coverage report
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## License
|
|
257
|
+
|
|
258
|
+
[Apache 2.0](../LICENSE)
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# authgent-server
|
|
2
|
+
|
|
3
|
+
The open-source OAuth 2.1 Authorization Server for AI agents — MCP-native, delegation-aware, with DPoP sender-constrained tokens and human-in-the-loop step-up authorization.
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/authgent-server/)
|
|
6
|
+
[](https://python.org)
|
|
7
|
+
[](../LICENSE)
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install authgent-server
|
|
13
|
+
|
|
14
|
+
# With PostgreSQL support
|
|
15
|
+
pip install authgent-server[postgres]
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Initialize (generates secret key, creates DB, generates signing key)
|
|
22
|
+
authgent-server init
|
|
23
|
+
|
|
24
|
+
# Start the server
|
|
25
|
+
authgent-server run
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Server starts at `http://localhost:8000`:
|
|
29
|
+
- `GET /.well-known/oauth-authorization-server` — server metadata
|
|
30
|
+
- `GET /.well-known/jwks.json` — public signing keys
|
|
31
|
+
- `GET /docs` — interactive Swagger UI
|
|
32
|
+
|
|
33
|
+
## CLI Commands
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
authgent-server init # Generate .env, create DB, signing key
|
|
37
|
+
authgent-server run # Start server (uvicorn)
|
|
38
|
+
authgent-server create-agent # Register an agent interactively
|
|
39
|
+
authgent-server migrate # Run Alembic migrations
|
|
40
|
+
authgent-server migrate --dry-run # Preview pending migrations
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## API Endpoints
|
|
44
|
+
|
|
45
|
+
### OAuth 2.1 Core
|
|
46
|
+
|
|
47
|
+
| Method | Path | Description |
|
|
48
|
+
|:-------|:-----|:------------|
|
|
49
|
+
| `POST` | `/register` | Dynamic client registration (RFC 7591) |
|
|
50
|
+
| `POST` | `/token` | Token endpoint — all grant types |
|
|
51
|
+
| `GET` | `/authorize` | Authorization code + PKCE (consent page) |
|
|
52
|
+
| `POST` | `/authorize` | Authorization code (consent submission) |
|
|
53
|
+
| `POST` | `/introspect` | Token introspection (RFC 7662) |
|
|
54
|
+
| `POST` | `/revoke` | Token revocation (RFC 7009) |
|
|
55
|
+
|
|
56
|
+
### Device Authorization (RFC 8628)
|
|
57
|
+
|
|
58
|
+
| Method | Path | Description |
|
|
59
|
+
|:-------|:-----|:------------|
|
|
60
|
+
| `POST` | `/device/authorize` | Request device + user codes |
|
|
61
|
+
| `POST` | `/device/approve` | Human approves device code |
|
|
62
|
+
| `POST` | `/device/deny` | Human denies device code |
|
|
63
|
+
|
|
64
|
+
### Step-Up Authorization (HITL)
|
|
65
|
+
|
|
66
|
+
| Method | Path | Description |
|
|
67
|
+
|:-------|:-----|:------------|
|
|
68
|
+
| `POST` | `/stepup` | Create step-up request |
|
|
69
|
+
| `GET` | `/stepup/{id}` | Poll step-up status |
|
|
70
|
+
| `POST` | `/stepup/{id}/approve` | Human approves |
|
|
71
|
+
| `POST` | `/stepup/{id}/deny` | Human denies |
|
|
72
|
+
|
|
73
|
+
### Agent Identity Registry
|
|
74
|
+
|
|
75
|
+
| Method | Path | Description |
|
|
76
|
+
|:-------|:-----|:------------|
|
|
77
|
+
| `POST` | `/agents` | Register agent (auto-creates OAuth client) |
|
|
78
|
+
| `GET` | `/agents` | List agents (paginated, filterable) |
|
|
79
|
+
| `GET` | `/agents/{id}` | Get agent details |
|
|
80
|
+
| `PATCH` | `/agents/{id}` | Update agent |
|
|
81
|
+
| `DELETE` | `/agents/{id}` | Deactivate agent |
|
|
82
|
+
|
|
83
|
+
### Discovery & Health
|
|
84
|
+
|
|
85
|
+
| Method | Path | Description |
|
|
86
|
+
|:-------|:-----|:------------|
|
|
87
|
+
| `GET` | `/.well-known/oauth-authorization-server` | Server metadata (RFC 8414) |
|
|
88
|
+
| `GET` | `/.well-known/openid-configuration` | OIDC-compatible alias |
|
|
89
|
+
| `GET` | `/.well-known/jwks.json` | Public signing keys |
|
|
90
|
+
| `GET` | `/.well-known/oauth-protected-resource` | Resource metadata (RFC 9728) |
|
|
91
|
+
| `GET` | `/health` | Liveness check |
|
|
92
|
+
| `GET` | `/ready` | Readiness (DB + signing keys) |
|
|
93
|
+
|
|
94
|
+
## Configuration
|
|
95
|
+
|
|
96
|
+
All settings via `AUTHGENT_*` environment variables. See [`.env.example`](.env.example) for the full list.
|
|
97
|
+
|
|
98
|
+
### Essential
|
|
99
|
+
|
|
100
|
+
| Variable | Default | Description |
|
|
101
|
+
|:---------|:--------|:------------|
|
|
102
|
+
| `AUTHGENT_SECRET_KEY` | *generated* | Master secret for HKDF key derivation |
|
|
103
|
+
| `AUTHGENT_DATABASE_URL` | `sqlite+aiosqlite:///./authgent.db` | Database URL |
|
|
104
|
+
| `AUTHGENT_HOST` | `0.0.0.0` | Bind address |
|
|
105
|
+
| `AUTHGENT_PORT` | `8000` | Bind port |
|
|
106
|
+
|
|
107
|
+
### Token Lifetimes
|
|
108
|
+
|
|
109
|
+
| Variable | Default | Description |
|
|
110
|
+
|:---------|:--------|:------------|
|
|
111
|
+
| `AUTHGENT_ACCESS_TOKEN_TTL` | `900` | Access token (15 min) |
|
|
112
|
+
| `AUTHGENT_REFRESH_TOKEN_TTL` | `86400` | Refresh token (24 hr) |
|
|
113
|
+
| `AUTHGENT_EXCHANGE_TOKEN_TTL` | `300` | Exchanged token (5 min) |
|
|
114
|
+
|
|
115
|
+
### Policy
|
|
116
|
+
|
|
117
|
+
| Variable | Default | Description |
|
|
118
|
+
|:---------|:--------|:------------|
|
|
119
|
+
| `AUTHGENT_MAX_DELEGATION_DEPTH` | `5` | Max delegation chain hops |
|
|
120
|
+
| `AUTHGENT_REQUIRE_DPOP` | `false` | Require DPoP on all token requests |
|
|
121
|
+
| `AUTHGENT_CONSENT_MODE` | `auto_approve` | `auto_approve`, `ui`, `headless` |
|
|
122
|
+
| `AUTHGENT_REGISTRATION_POLICY` | `open` | `open`, `token`, `admin` |
|
|
123
|
+
|
|
124
|
+
### Pluggable Providers
|
|
125
|
+
|
|
126
|
+
| Variable | Default | Description |
|
|
127
|
+
|:---------|:--------|:------------|
|
|
128
|
+
| `AUTHGENT_ATTESTATION_PROVIDER` | *null* | Dotted import path |
|
|
129
|
+
| `AUTHGENT_POLICY_PROVIDER` | *null* | Custom policy enforcement |
|
|
130
|
+
| `AUTHGENT_HITL_PROVIDER` | *webhook* | Step-up notification backend |
|
|
131
|
+
| `AUTHGENT_KEY_PROVIDER` | *database* | Signing key storage |
|
|
132
|
+
| `AUTHGENT_EVENT_EMITTER` | *database* | Audit event backend |
|
|
133
|
+
| `AUTHGENT_CLAIM_ENRICHER` | *null* | Custom token claim enrichment |
|
|
134
|
+
|
|
135
|
+
## Deployment
|
|
136
|
+
|
|
137
|
+
### Docker
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
docker compose up -d
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The included [`docker-compose.yml`](docker-compose.yml) runs the server with PostgreSQL.
|
|
144
|
+
|
|
145
|
+
### Docker (standalone)
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
docker build -t authgent-server .
|
|
149
|
+
docker run -p 8000:8000 \
|
|
150
|
+
-e AUTHGENT_SECRET_KEY=your-secret-key \
|
|
151
|
+
-e AUTHGENT_DATABASE_URL=sqlite+aiosqlite:///./authgent.db \
|
|
152
|
+
authgent-server
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Production Checklist
|
|
156
|
+
|
|
157
|
+
- [ ] Set a strong `AUTHGENT_SECRET_KEY` (64+ characters)
|
|
158
|
+
- [ ] Use PostgreSQL (`AUTHGENT_DATABASE_URL=postgresql+asyncpg://...`)
|
|
159
|
+
- [ ] Run migrations: `authgent-server migrate`
|
|
160
|
+
- [ ] Set `AUTHGENT_REGISTRATION_POLICY=token` or `admin`
|
|
161
|
+
- [ ] Set `AUTHGENT_CONSENT_MODE=ui` for human-facing flows
|
|
162
|
+
- [ ] Enable DPoP: `AUTHGENT_REQUIRE_DPOP=true`
|
|
163
|
+
- [ ] Configure CORS origins: `AUTHGENT_CORS_ORIGINS=["https://your-app.com"]`
|
|
164
|
+
- [ ] Put behind a reverse proxy (nginx/Caddy) with TLS
|
|
165
|
+
- [ ] Set up log aggregation (structured JSON output)
|
|
166
|
+
|
|
167
|
+
## Architecture
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
Endpoints → Services → Models → DB
|
|
171
|
+
(thin) (stateless) (ORM) (async)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
- **Endpoints** — FastAPI routers, HTTP validation, dependency injection
|
|
175
|
+
- **Services** — All business logic, receive `db: AsyncSession` per call
|
|
176
|
+
- **Models** — SQLAlchemy 2.0 async ORM, 9 tables
|
|
177
|
+
- **Providers** — 7 pluggable Python Protocol interfaces (attestation, policy, HITL, keys, events, claim enricher, human auth)
|
|
178
|
+
|
|
179
|
+
See [ARCHITECTURE.md](../ARCHITECTURE.md) for the full implementation design.
|
|
180
|
+
|
|
181
|
+
## Development
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# Setup
|
|
185
|
+
git clone https://github.com/authgent/authgent.git
|
|
186
|
+
cd authgent/server
|
|
187
|
+
pip install -e ".[dev,migrations]"
|
|
188
|
+
authgent-server init
|
|
189
|
+
|
|
190
|
+
# Test (192 tests)
|
|
191
|
+
pytest -v
|
|
192
|
+
|
|
193
|
+
# Lint + format
|
|
194
|
+
ruff check . && ruff format --check .
|
|
195
|
+
|
|
196
|
+
# Type check
|
|
197
|
+
mypy authgent_server/ --ignore-missing-imports
|
|
198
|
+
|
|
199
|
+
# Coverage
|
|
200
|
+
coverage run -m pytest tests/ && coverage report
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## License
|
|
204
|
+
|
|
205
|
+
[Apache 2.0](../LICENSE)
|