AAuth protocol implementation for Python
Project description
AAuth Protocol Implementation
A Python implementation of the AAuth protocol for learning and understanding the protocol through hands-on coding.
Library Installation
This project includes a reusable aauth Python library that can be installed and used in other projects.
Installing in the Current Project
If you're working within this project:
# Install in editable mode (recommended for development)
pip install -e .
# Or install normally
pip install .
Installing in Other Projects on the Same Computer
To use this library in other projects on the same computer:
-
Navigate to your other project directory:
cd /path/to/your/other/project
-
Activate your project's virtual environment:
# If using venv source .venv/bin/activate # or venv/bin/activate # If using conda conda activate your-env-name
-
Install the library in editable mode using the absolute path:
pip install -e /Users/christian.posta/dev/code/aauth
Or if you're in a different location, use the full path to this project:
pip install -e /full/path/to/aauth/project
-
Verify the installation:
pip list | grep aauth python -c "import aauth; print(aauth.__file__)"
The
__file__should point to the source directory, confirming editable mode. -
Use the library in your code:
import aauth # Now you can use all the library functions private_key, public_key = aauth.generate_ed25519_keypair()
Note: Editable mode (-e) means changes to the library source code will be immediately available in your other projects without reinstalling. This is ideal for development.
Once installed, you can import and use the library:
import aauth
# Generate a key pair
private_key, public_key = aauth.generate_ed25519_keypair()
# Sign a request
signed_headers = aauth.sign_request(
method="GET",
target_uri="https://resource.example/api/data",
headers={},
body=None,
private_key=private_key
)
# Verify a signature
is_valid = aauth.verify_signature(
method="GET",
target_uri="https://resource.example/api/data",
headers=signed_headers,
body=None,
signature_input_header=signed_headers["Signature-Input"],
signature_header=signed_headers["Signature"],
signature_key_header=signed_headers["Signature-Key"]
)
See the Library Usage section below for more examples.
Overview
This project implements the AAuth protocol incrementally, phase by phase:
- Phase 1: Pseudonymous flow (proof-of-possession without identity)
- Phase 2: Agent identity (JWKS-based identity verification)
- Phase 3: Autonomous authorization (full token flow)
- Phase 4: User delegation (OAuth-like authorization code flow)
- Phase 5: Agent is Resource (SSO and unified token flow)
- Phase 6: Agent Delegation (agent tokens for distributed instances)
- Phase 7: Token Exchange (multi-hop resource access with delegation chain)
Quick Start
Setup
- Install dependencies:
# (Recommended) Use virtual environment
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Running Demos
Phase 1: Pseudonymous Flow
Demonstrates basic proof-of-possession without identity using sig=hwk scheme:
python demo_phase1.py
Phase 2: Agent Identity via JWKS
Demonstrates agent identity verification using sig=jwks scheme:
python demo_phase2.py
Phase 3: Autonomous Authorization
Demonstrates complete token flow without user interaction:
python demo_phase3.py
Phase 4: User Delegation
Demonstrates OAuth-like authorization code flow with user consent:
Automated mode (uses user simulator):
python demo_phase4.py
Manual mode (browser-based testing):
python demo_phase4.py --manual
Phase 5: Agent is Resource
Demonstrates agent authenticating users to itself for SSO and API access:
Automated mode (uses user simulator):
python demo_phase5.py
Manual mode (browser-based testing):
python demo_phase5.py --manual
Phase 6: Agent Delegation
Demonstrates agent delegation where agent servers issue agent tokens to delegates:
Automated mode:
python demo_phase6.py
Phase 7: Token Exchange
Demonstrates multi-hop resource access where a resource exchanges an upstream auth token to access a downstream resource:
Automated mode:
python demo_phase7.py
Testing
Run all tests:
pytest tests/ -v
Run tests for a specific phase:
pytest tests/test_phase1.py -v
pytest tests/test_phase2.py -v
pytest tests/test_phase3.py -v
pytest tests/test_phase4.py -v
pytest tests/test_phase5.py -v
pytest tests/test_phase6.py -v
pytest tests/test_phase7.py -v
Phase Overview
Phase 1: Pseudonymous Flow
- Agent signs requests with
sig=hwk(public key in header) - Resource validates signatures
- No tokens, no identity - just signature verification
See PHASE1.md for detailed documentation.
Phase 2: Agent Identity via JWKS
- Agent publishes metadata at
/.well-known/aauth-agent - Agent publishes JWKS at
/jwks.json - Resource can verify agent identity using
sig=jwksscheme - Separate endpoints (
/data-hwk,/data-jwks) for both schemes
See PHASE2.md for detailed documentation.
Phase 3: Autonomous Authorization
- Resources issue resource tokens when agents request access
- Agents present resource tokens to auth servers
- Auth servers validate resource tokens and issue auth tokens
- Agents use auth tokens to access protected resources
- Complete token flow without user interaction
See PHASE3.md for detailed documentation.
Phase 4: User Delegation
- Auth servers issue
request_tokenwhen user consent is required - Agents redirect users to auth server's authorization endpoint
- Users authenticate and grant consent
- Auth server redirects back with authorization code
- Agents exchange code for auth tokens with
subclaim
See PHASE4.md for detailed documentation.
Phase 5: Agent is Resource
- Agent requests authorization directly with
scope(noresource_token) - Agent identifier matches resource identifier (agent authenticates users to itself)
- Auth token has
aud= agent identifier andagentclaim omitted - Unified token serves both SSO (user identity) and API access purposes
- Solves OIDC limitation where ID tokens and access tokens are separate
See PHASE5.md for detailed documentation.
Phase 6: Agent Delegation
- Agent servers issue agent tokens (
agent+jwt) to agent delegates - Delegates use
scheme=jwtwith agent tokens to sign requests - Resources and auth servers validate agent tokens per SPEC.md Section 5.7
- Delegates share agent server's identity but use ephemeral keys
- Delegate identifier (
sub) persists across key rotations - Auth tokens include
agent_delegateclaim when issued to delegates
See PHASE6.md for detailed documentation.
Phase 7: Token Exchange
- Resources can act as agents to access downstream resources
- Upstream auth tokens are exchanged for downstream auth tokens
- Downstream auth server validates upstream token and federation trust
- Exchanged tokens include
actclaim showing the delegation chain - User context (
sub) is preserved through the chain - Enables autonomous multi-hop resource access
See PHASE7.md for detailed documentation.
Running Individual Participants
Run Resource Server:
python -m participants.resource
Run Agent:
python -m participants.agent
Run Auth Server:
python -m participants.auth_server
Library Usage
The aauth library provides a framework-agnostic implementation of the AAuth protocol. Here are some common usage patterns:
Key Generation
import aauth
# Generate Ed25519 key pair
private_key, public_key = aauth.generate_ed25519_keypair()
# Convert to JWK format
jwk = aauth.public_key_to_jwk(public_key, kid="key-1")
# Calculate JWK thumbprint
thumbprint = aauth.calculate_jwk_thumbprint(jwk)
HTTP Message Signing
import aauth
# Sign a request with hwk scheme (pseudonymous)
signed_headers = aauth.sign_request(
method="GET",
target_uri="https://resource.example/api/data",
headers={"Host": "resource.example"},
body=None,
private_key=private_key,
sig_scheme="hwk"
)
# Sign with jwks scheme (agent identity)
signed_headers = aauth.sign_request(
method="POST",
target_uri="https://resource.example/api/data",
headers={"Content-Type": "application/json"},
body=b'{"key": "value"}',
private_key=private_key,
sig_scheme="jwks",
id="https://agent.example",
kid="key-1"
)
# Sign with jwt scheme (using auth token)
signed_headers = aauth.sign_request(
method="GET",
target_uri="https://resource.example/api/data",
headers={},
body=None,
private_key=private_key,
sig_scheme="jwt",
jwt=auth_token
)
Signature Verification
import aauth
# Verify a signature
is_valid = aauth.verify_signature(
method=request.method,
target_uri=str(request.url),
headers=dict(request.headers),
body=request_body,
signature_input_header=request.headers.get("Signature-Input"),
signature_header=request.headers.get("Signature"),
signature_key_header=request.headers.get("Signature-Key"),
jwks_fetcher=my_jwks_fetcher # Required for jwks/jwt schemes
)
Token Creation and Validation
import aauth
# Create a resource token
resource_token = aauth.create_resource_token(
iss="https://resource.example",
aud="https://auth.example",
agent="https://agent.example",
agent_jkt=agent_thumbprint,
scope="data.read data.write",
private_key=resource_private_key,
kid="resource-key-1"
)
# Create an auth token
auth_token = aauth.create_auth_token(
iss="https://auth.example",
aud="https://resource.example",
agent="https://agent.example",
cnf_jwk=agent_jwk,
scope="data.read",
private_key=auth_private_key,
kid="auth-key-1"
)
# Verify an agent token
claims = aauth.verify_agent_token(
token=agent_token,
jwks_fetcher=my_jwks_fetcher,
expected_aud="https://resource.example"
)
# Parse token claims (without verification)
claims = aauth.parse_token_claims(token)
Agent-Auth Header Parsing
import aauth
# Parse Agent-Auth challenge header
challenge = aauth.parse_agent_auth_header(
"httpsig; identity=?1; auth-token; resource_token=\"...\"; auth_server=\"https://auth.example\""
)
# Build Agent-Auth challenge
challenge_header = aauth.build_agent_auth_challenge(
require_signature=True,
require_identity=True,
require_auth_token=True,
resource_token=resource_token,
auth_server="https://auth.example"
)
High-Level Agent and Resource APIs
import aauth
# Agent request signer
signer = aauth.AgentRequestSigner(
private_key=private_key,
agent_id="https://agent.example",
agent_token=agent_token
)
signed_headers = signer.sign_request(
method="GET",
target_uri="https://resource.example/api/data",
headers={},
body=None,
sig_scheme="jwt"
)
# Resource request verifier
verifier = aauth.RequestVerifier(
canonical_authorities=["resource.example:443"],
jwks_fetcher=my_jwks_fetcher
)
result = verifier.verify_request(
method="GET",
target_uri="https://resource.example/api/data",
headers=request_headers,
body=request_body,
require_identity=True,
require_auth_token=True
)
if result["valid"]:
print(f"Agent ID: {result['agent_id']}")
print(f"Scopes: {result['scopes']}")
Framework Integration
The library is framework-agnostic. Here's an example for FastAPI:
from fastapi import FastAPI, Request
from aauth import RequestVerifier, AAuthRequest
app = FastAPI()
verifier = RequestVerifier(canonical_authorities=["api.example.com"])
@app.get("/protected")
async def protected_endpoint(request: Request):
# Convert FastAPI request to AAuthRequest
aauth_req = AAuthRequest.from_fastapi_request(request)
# Verify signature
result = verifier.verify_request(
method=aauth_req.method,
target_uri=str(request.url),
headers=dict(request.headers),
body=await request.body()
)
if not result["valid"]:
return {"error": result["error"]}, 401
return {"data": "protected resource", "agent": result["agent_id"]}
Project Structure
aauth/
├── aauth/ # Main library package (installable)
│ ├── signing/ # HTTP Message Signing (RFC 9421)
│ ├── keys/ # Key management and JWK operations
│ ├── tokens/ # JWT token handling
│ ├── headers/ # HTTP header parsing/building
│ ├── metadata/ # Metadata discovery
│ ├── http/ # HTTP abstraction layer
│ ├── agent/ # Agent role implementation
│ └── resource/ # Resource role implementation
├── core/ # Legacy core utilities (deprecated, use aauth.*)
├── participants/ # Protocol participants (demo implementations)
├── flows/ # Flow implementations
└── tests/ # Test suite
Documentation
- PHASE1.md - Phase 1 implementation details
- PHASE2.md - Phase 2 implementation details
- PHASE3.md - Phase 3 implementation details
- PHASE4.md - Phase 4 implementation details
- PHASE5.md - Phase 5 implementation details
- PHASE6.md - Phase 6 implementation details
- PHASE7.md - Phase 7 implementation details
- SPEC.md - AAuth protocol specification
- PLAN.md - Overall implementation plan
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aauth-0.1.0.tar.gz.
File metadata
- Download URL: aauth-0.1.0.tar.gz
- Upload date:
- Size: 97.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2a970dc435199e7276759351b4675254d3d130df5695f25a25379540771dce7f
|
|
| MD5 |
24ec4ab45aacd822addaac6ff62ba4e7
|
|
| BLAKE2b-256 |
3bcdcd10c6b4669d8d9cc620bf3fe133d03efde88b81cb655483818b05b92096
|
File details
Details for the file aauth-0.1.0-py3-none-any.whl.
File metadata
- Download URL: aauth-0.1.0-py3-none-any.whl
- Upload date:
- Size: 42.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
04809ab3321f0658b5656ead89edda3a36db6b68fcc490b40428bf3a9c77e8d7
|
|
| MD5 |
66ad491f2d527d8b2a01cee36ad8fb06
|
|
| BLAKE2b-256 |
99163b9d4f92852f8b420ddaee9c927be3975989af6ee635edfdec92791bb023
|