Pico-Auth
Minimal JWT auth server for the Pico ecosystem.
Pico-Auth is a ready-to-run authentication server built on top of the pico-framework stack. It provides:
- JWT tokens with auto-generated key pairs (RS256 default, ML-DSA-65/87 optional)
- Refresh token rotation with SHA-256 hashed storage
- RBAC with four built-in roles:
superadmin,org_admin,operator,viewer - Group management with CRUD API, membership, and
groupsJWT claim - OIDC discovery endpoints (
.well-known/openid-configuration, JWKS) - Bcrypt password hashing (72-byte input limit enforced)
- Post-quantum ready: ML-DSA-65 / ML-DSA-87 signing via optional
pqcextra - Zero-config startup with auto-created admin user
Requires Python 3.11+
Architecture
Pico-Auth uses the full Pico stack with dependency injection:
| Layer | Component | Decorator |
|---|---|---|
| Config | AuthSettings |
@configured(prefix="auth") |
| Models | User, RefreshToken, Group, GroupMember |
SQLAlchemy AppBase |
| Repository | UserRepository, RefreshTokenRepository, GroupRepository |
@component |
| Service | AuthService, GroupService |
@component |
| Security | JWTProvider, PasswordService, LocalJWKSProvider |
@component |
| Routes | AuthController, GroupController, OIDCController |
@controller |
Installation
pip install -e ".[dev]"
# With post-quantum (ML-DSA) support
pip install -e ".[dev,pqc]"
Quick Start
1. Run the Server
python -m pico_auth.main
The server starts on http://localhost:8100 with:
- An auto-created admin user (
admin@pico.local/admin) - SQLite database at
auth.db - Auto-generated keys at
~/.pico-auth/(RSA PEM or ML-DSA binary, depending on algorithm)
2. Register a User
curl -X POST http://localhost:8100/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"email": "alice@example.com", "password": "secret123", "display_name": "Alice"}'
3. Login
curl -X POST http://localhost:8100/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "alice@example.com", "password": "secret123"}'
Returns:
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "a1b2c3d4...",
"token_type": "Bearer",
"expires_in": 900
}
4. Access Protected Endpoint
curl http://localhost:8100/api/v1/auth/me \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."
API Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/v1/auth/register |
No | Register a new user |
| POST | /api/v1/auth/login |
No | Login and get tokens |
| POST | /api/v1/auth/refresh |
No | Refresh access token |
| GET | /api/v1/auth/me |
Bearer | Get current user profile |
| POST | /api/v1/auth/me/password |
Bearer | Change password |
| GET | /api/v1/auth/users |
Admin | List all users |
| PUT | /api/v1/auth/users/{id}/role |
Admin | Update user role |
| GET | /api/v1/auth/jwks |
No | JSON Web Key Set |
| POST | /api/v1/groups |
Admin | Create a group |
| GET | /api/v1/groups |
Bearer | List groups (by org) |
| GET | /api/v1/groups/{id} |
Bearer | Get group with members |
| PUT | /api/v1/groups/{id} |
Admin | Update group |
| DELETE | /api/v1/groups/{id} |
Admin | Delete group |
| POST | /api/v1/groups/{id}/members |
Admin | Add member to group |
| DELETE | /api/v1/groups/{id}/members/{uid} |
Admin | Remove member |
| GET | /.well-known/openid-configuration |
No | OIDC discovery |
Configuration
All settings are loaded from application.yaml and can be overridden with environment variables:
auth:
data_dir: "~/.pico-auth" # Key storage directory
access_token_expire_minutes: 15 # JWT lifetime
refresh_token_expire_days: 7 # Refresh token lifetime
issuer: "http://localhost:8100" # JWT issuer claim
audience: "pico-bot" # JWT audience claim
algorithm: "RS256" # RS256, ML-DSA-65, or ML-DSA-87
auto_create_admin: true # Create admin on startup
admin_email: "admin@pico.local" # Default admin email
admin_password: "admin" # Default admin password
database:
url: "sqlite+aiosqlite:///auth.db" # Database URL
echo: false # SQL logging
auth_client:
enabled: true # Enable auth middleware
issuer: "http://localhost:8100" # Must match auth.issuer
audience: "pico-bot" # Must match auth.audience
accepted_algorithms: # Algorithms accepted for verification
- "RS256"
- "ML-DSA-65"
- "ML-DSA-87"
fastapi:
title: "Pico Auth API"
version: "0.2.0"
Environment variable override example:
AUTH_ISSUER=https://auth.myapp.com AUTH_ADMIN_PASSWORD=strong-password python -m pico_auth.main
# With ML-DSA-65 post-quantum algorithm
AUTH_ALGORITHM=ML-DSA-65 python -m pico_auth.main
JWT Token Claims
Access tokens include:
| Claim | Description |
|---|---|
sub |
User ID |
email |
User email |
role |
User role (superadmin, org_admin, operator, viewer) |
org_id |
Organization ID |
groups |
Group IDs the user belongs to |
iss |
Issuer URL |
aud |
Audience |
iat |
Issued at (Unix timestamp) |
exp |
Expiration (Unix timestamp) |
jti |
Unique token ID |
Ecosystem
Pico-Auth is built on:
| Package | Role |
|---|---|
| pico-ioc | Dependency injection container |
| pico-boot | Bootstrap and plugin discovery |
| pico-fastapi | FastAPI integration with @controller |
| pico-sqlalchemy | Async SQLAlchemy with SessionManager |
| pico-client-auth | JWT auth middleware with SecurityContext |
Development
# Install in dev mode
pip install -e ".[dev]"
# Run tests
pytest tests/ -v
# Run with coverage
pytest --cov=pico_auth --cov-report=term-missing tests/
# Full test matrix
tox
# Lint
ruff check pico_auth/ tests/
# Docker E2E tests (requires Docker and ../pico-client-auth)
pytest tests/test_docker_e2e.py -m docker -v
Docker E2E tests build a local image (Dockerfile.local), start a container, and run HTTP tests against it. They are excluded from the default test suite — use -m docker to run them. See Docker E2E Test for details.
License
MIT - LICENSE
Metadata
Release files for pico-auth 0.3.0.post0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pico_auth-0.3.0.post0.tar.gz | 54.3 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pico_auth-0.3.0.post0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 75.4 kB
Release files / pico_auth-0.3.0.post0.tar.gz
| Download URL | pico_auth-0.3.0.post0.tar.gz |
|---|---|
| Size | 54.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
194e742977629918ac5b5bde70cb3fe5138fa8c823405758f9b0ea2ee5595d06
|
|
BLAKE2b-256 checksum How to use checksums |
f9d70adc51f8293de8ef90b07a50273a95c8b4844fe75fd43c768e54d892fe81
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 10, 2026.
Transparency logRelease files / pico_auth-0.3.0.post0-py3-none-any.whl
| Download URL | pico_auth-0.3.0.post0-py3-none-any.whl |
|---|---|
| Size | 21.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9ba71760eb78d4ba31e4f7a836c475a6b3c64b9c7f312683970245ba0f659996
|
|
BLAKE2b-256 checksum How to use checksums |
5ca37be73b288f31a3ec6a327a542f5b5c249bc35bcd4ce252bbdf5427a48dc2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 10, 2026.
Transparency logSecurity for pico-auth 0.3.0.post0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for pico_auth-0.3.0.post0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 10, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.