pico-server-auth 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.
Files changed (69) hide show
  1. pico_server_auth-0.1.0/.coveragerc +7 -0
  2. pico_server_auth-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +24 -0
  3. pico_server_auth-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +15 -0
  4. pico_server_auth-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +13 -0
  5. pico_server_auth-0.1.0/.github/dependabot.yml +10 -0
  6. pico_server_auth-0.1.0/.github/workflows/ci.yml +67 -0
  7. pico_server_auth-0.1.0/.github/workflows/codeql.yml +21 -0
  8. pico_server_auth-0.1.0/.github/workflows/docs.yml +48 -0
  9. pico_server_auth-0.1.0/.github/workflows/publish-to-pypi.yml +24 -0
  10. pico_server_auth-0.1.0/AGENTS.md +56 -0
  11. pico_server_auth-0.1.0/CHANGELOG.md +21 -0
  12. pico_server_auth-0.1.0/CLAUDE.md +34 -0
  13. pico_server_auth-0.1.0/CODE_OF_CONDUCT.md +35 -0
  14. pico_server_auth-0.1.0/CONTRIBUTING.md +37 -0
  15. pico_server_auth-0.1.0/LICENSE +21 -0
  16. pico_server_auth-0.1.0/MANIFEST.in +5 -0
  17. pico_server_auth-0.1.0/PKG-INFO +169 -0
  18. pico_server_auth-0.1.0/README.md +129 -0
  19. pico_server_auth-0.1.0/SECURITY.md +11 -0
  20. pico_server_auth-0.1.0/docs/architecture.md +133 -0
  21. pico_server_auth-0.1.0/docs/faq.md +62 -0
  22. pico_server_auth-0.1.0/docs/getting-started.md +101 -0
  23. pico_server_auth-0.1.0/docs/hooks.py +7 -0
  24. pico_server_auth-0.1.0/docs/how-to/custom-challenge-store.md +121 -0
  25. pico_server_auth-0.1.0/docs/how-to/embed-in-app.md +90 -0
  26. pico_server_auth-0.1.0/docs/how-to/index.md +10 -0
  27. pico_server_auth-0.1.0/docs/how-to/standalone.md +85 -0
  28. pico_server_auth-0.1.0/docs/how-to/testing.md +190 -0
  29. pico_server_auth-0.1.0/docs/index.md +65 -0
  30. pico_server_auth-0.1.0/docs/javascripts/extra.js +10 -0
  31. pico_server_auth-0.1.0/docs/reference/config.md +73 -0
  32. pico_server_auth-0.1.0/docs/reference/endpoints.md +191 -0
  33. pico_server_auth-0.1.0/docs/reference/index.md +20 -0
  34. pico_server_auth-0.1.0/docs/requirements.txt +7 -0
  35. pico_server_auth-0.1.0/docs/skills.md +15 -0
  36. pico_server_auth-0.1.0/docs/stylesheets/extra.css +52 -0
  37. pico_server_auth-0.1.0/docs/troubleshooting.md +55 -0
  38. pico_server_auth-0.1.0/docs/user-guide/index.md +33 -0
  39. pico_server_auth-0.1.0/docs/user-guide/jwks.md +91 -0
  40. pico_server_auth-0.1.0/docs/user-guide/password-auth.md +70 -0
  41. pico_server_auth-0.1.0/docs/user-guide/wallet-auth.md +194 -0
  42. pico_server_auth-0.1.0/examples/embedded_app.py +49 -0
  43. pico_server_auth-0.1.0/examples/standalone_auth.py +33 -0
  44. pico_server_auth-0.1.0/examples/wallet_login.py +54 -0
  45. pico_server_auth-0.1.0/mkdocs.yml +158 -0
  46. pico_server_auth-0.1.0/pyproject.toml +95 -0
  47. pico_server_auth-0.1.0/setup.cfg +4 -0
  48. pico_server_auth-0.1.0/src/pico_server_auth/__init__.py +15 -0
  49. pico_server_auth-0.1.0/src/pico_server_auth/_version.py +1 -0
  50. pico_server_auth-0.1.0/src/pico_server_auth/challenge_store.py +57 -0
  51. pico_server_auth-0.1.0/src/pico_server_auth/config.py +24 -0
  52. pico_server_auth-0.1.0/src/pico_server_auth/controllers.py +129 -0
  53. pico_server_auth-0.1.0/src/pico_server_auth/py.typed +0 -0
  54. pico_server_auth-0.1.0/src/pico_server_auth/token_issuer.py +100 -0
  55. pico_server_auth-0.1.0/src/pico_server_auth/wallet_verifier.py +81 -0
  56. pico_server_auth-0.1.0/src/pico_server_auth.egg-info/PKG-INFO +169 -0
  57. pico_server_auth-0.1.0/src/pico_server_auth.egg-info/SOURCES.txt +67 -0
  58. pico_server_auth-0.1.0/src/pico_server_auth.egg-info/dependency_links.txt +1 -0
  59. pico_server_auth-0.1.0/src/pico_server_auth.egg-info/entry_points.txt +2 -0
  60. pico_server_auth-0.1.0/src/pico_server_auth.egg-info/requires.txt +13 -0
  61. pico_server_auth-0.1.0/src/pico_server_auth.egg-info/top_level.txt +1 -0
  62. pico_server_auth-0.1.0/test/Dockerfile.dev +26 -0
  63. pico_server_auth-0.1.0/tests/__init__.py +0 -0
  64. pico_server_auth-0.1.0/tests/conftest.py +21 -0
  65. pico_server_auth-0.1.0/tests/test_challenge_store.py +64 -0
  66. pico_server_auth-0.1.0/tests/test_controllers.py +213 -0
  67. pico_server_auth-0.1.0/tests/test_token_issuer.py +81 -0
  68. pico_server_auth-0.1.0/tests/test_wallet_verifier.py +60 -0
  69. pico_server_auth-0.1.0/tox.ini +21 -0
@@ -0,0 +1,7 @@
1
+ [run]
2
+ branch = True
3
+ source = pico_server_auth
4
+ omit = */_version.py
5
+
6
+ [report]
7
+ show_missing = True
@@ -0,0 +1,24 @@
1
+ name: Bug Report
2
+ description: Report a bug
3
+ labels: [bug]
4
+ body:
5
+ - type: textarea
6
+ id: description
7
+ attributes: { label: Description }
8
+ validations: { required: true }
9
+ - type: textarea
10
+ id: steps
11
+ attributes: { label: Steps to Reproduce, render: python }
12
+ validations: { required: true }
13
+ - type: textarea
14
+ id: expected
15
+ attributes: { label: Expected Behavior }
16
+ validations: { required: true }
17
+ - type: input
18
+ id: version
19
+ attributes: { label: Package Version }
20
+ validations: { required: true }
21
+ - type: input
22
+ id: python
23
+ attributes: { label: Python Version }
24
+ validations: { required: true }
@@ -0,0 +1,15 @@
1
+ name: Feature Request
2
+ description: Suggest an improvement
3
+ labels: [enhancement]
4
+ body:
5
+ - type: textarea
6
+ id: problem
7
+ attributes: { label: Problem }
8
+ validations: { required: true }
9
+ - type: textarea
10
+ id: solution
11
+ attributes: { label: Proposed Solution }
12
+ validations: { required: true }
13
+ - type: textarea
14
+ id: alternatives
15
+ attributes: { label: Alternatives Considered }
@@ -0,0 +1,13 @@
1
+ ## Summary
2
+
3
+ ## Changes
4
+
5
+ -
6
+
7
+ ## Checklist
8
+
9
+ - [ ] Tests pass (`pytest tests/ -v`)
10
+ - [ ] Linting passes (`ruff check src/ tests/`)
11
+ - [ ] CHANGELOG.md updated (if user-facing)
12
+ - [ ] No new runtime dependencies
13
+ - [ ] Single-line commit messages
@@ -0,0 +1,10 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ - package-ecosystem: "pip"
8
+ directory: "/"
9
+ schedule:
10
+ interval: "weekly"
@@ -0,0 +1,67 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+ branches: [main]
7
+
8
+ jobs:
9
+ lint:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: "3.11"
16
+ - run: pip install ruff
17
+ - run: ruff check src/ tests/
18
+ - run: ruff format --check src/ tests/
19
+
20
+ tests:
21
+ runs-on: ubuntu-latest
22
+ strategy:
23
+ matrix:
24
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ with:
28
+ fetch-depth: 0
29
+ - uses: actions/setup-python@v5
30
+ with:
31
+ python-version: ${{ matrix.python-version }}
32
+ - run: pip install tox
33
+ - name: Run tests with coverage
34
+ env:
35
+ SETUPTOOLS_SCM_PRETEND_VERSION: "0.1.0"
36
+ run: |
37
+ tox -e cov
38
+ mv .coverage .coverage.${{ matrix.python-version }}
39
+ - uses: actions/upload-artifact@v4
40
+ with:
41
+ name: coverage-${{ matrix.python-version }}
42
+ path: .coverage.${{ matrix.python-version }}
43
+ include-hidden-files: true
44
+ if-no-files-found: error
45
+
46
+ coverage:
47
+ needs: tests
48
+ runs-on: ubuntu-latest
49
+ steps:
50
+ - uses: actions/checkout@v4
51
+ - uses: actions/setup-python@v5
52
+ with:
53
+ python-version: "3.12"
54
+ - uses: actions/download-artifact@v4
55
+ with:
56
+ path: coverage-reports
57
+ - name: Combine and upload
58
+ run: |
59
+ pip install coverage
60
+ files=$(find coverage-reports -type f -name ".coverage.*")
61
+ if [ -z "$files" ]; then echo "No coverage files"; exit 1; fi
62
+ coverage combine $files
63
+ coverage xml
64
+ - uses: codecov/codecov-action@v4
65
+ with:
66
+ token: ${{ secrets.CODECOV_TOKEN }}
67
+ files: coverage.xml
@@ -0,0 +1,21 @@
1
+ name: CodeQL
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+ branches: [main]
7
+ schedule:
8
+ - cron: "0 6 * * 1"
9
+
10
+ permissions:
11
+ security-events: write
12
+ contents: read
13
+
14
+ jobs:
15
+ analyze:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - uses: github/codeql-action/init@v3
20
+ with: { languages: python }
21
+ - uses: github/codeql-action/analyze@v3
@@ -0,0 +1,48 @@
1
+ name: Docs
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ paths: [docs/**, mkdocs.yml]
6
+ pull_request:
7
+ branches: [main]
8
+ paths: [docs/**, mkdocs.yml]
9
+ workflow_dispatch:
10
+
11
+ permissions:
12
+ contents: write
13
+ pages: write
14
+ id-token: write
15
+
16
+ concurrency:
17
+ group: pages
18
+ cancel-in-progress: false
19
+
20
+ jobs:
21
+ validate:
22
+ if: github.event_name == 'pull_request'
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+ with: { fetch-depth: 0 }
27
+ - uses: actions/setup-python@v5
28
+ with: { python-version: "3.12" }
29
+ - run: pip install -r docs/requirements.txt
30
+ - run: mkdocs build --strict
31
+
32
+ deploy:
33
+ if: github.event_name != 'pull_request'
34
+ runs-on: ubuntu-latest
35
+ environment:
36
+ name: github-pages
37
+ url: ${{ steps.deployment.outputs.page_url }}
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+ with: { fetch-depth: 0 }
41
+ - uses: actions/setup-python@v5
42
+ with: { python-version: "3.12" }
43
+ - run: pip install -r docs/requirements.txt
44
+ - run: mkdocs build --strict --verbose
45
+ - uses: actions/upload-pages-artifact@v3
46
+ with: { path: site }
47
+ - id: deployment
48
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,24 @@
1
+ name: Publish to PyPI
2
+ on:
3
+ release:
4
+ types: [published]
5
+
6
+ permissions:
7
+ id-token: write
8
+ contents: read
9
+
10
+ jobs:
11
+ deploy:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ with: { fetch-depth: 0 }
16
+ - uses: actions/setup-python@v5
17
+ with: { python-version: "3.x" }
18
+ - run: pip install build
19
+ - run: python -m build
20
+ - uses: pypa/gh-action-pypi-publish@release/v1
21
+ with:
22
+ skip-existing: true
23
+ verify-metadata: true
24
+ attestations: true
@@ -0,0 +1,56 @@
1
+ # pico-server-auth
2
+
3
+ Embeddable auth server module for pico-boot. JWT issuance, wallet challenge/verify login, password login, and JWKS endpoint as FastAPI controllers.
4
+
5
+ ## Commands
6
+
7
+ ```bash
8
+ pip install -e ".[test]" # Install in dev mode
9
+ pytest tests/ -v # Run tests
10
+ pytest --cov=pico_server_auth --cov-report=term-missing tests/ # Coverage
11
+ tox # Full matrix (3.11-3.14)
12
+ ```
13
+
14
+ ## Project Structure
15
+
16
+ ```
17
+ src/pico_server_auth/
18
+ __init__.py # Public API exports (ChallengeStore, InMemoryChallengeStore, ServerAuthSettings, TokenIssuer, WalletVerifier)
19
+ config.py # ServerAuthSettings (@configured, prefix="server_auth", mapping="tree")
20
+ controllers.py # AuthController (@controller, prefix="/auth") — jwks, challenge, wallet_login, password_login
21
+ challenge_store.py # ChallengeStore protocol + InMemoryChallengeStore (@component)
22
+ wallet_verifier.py # WalletVerifier (@component) — ML-DSA-65, Ed25519, secp256k1
23
+ token_issuer.py # TokenIssuer (@component) — RS256 JWT signing + JWKS export
24
+ ```
25
+
26
+ ## Key Concepts
27
+
28
+ - **`AuthController`**: FastAPI controller with `prefix="/auth"`. All endpoints are `@allow_anonymous` (public auth API).
29
+ - **`ServerAuthSettings`**: Configured via `@configured(prefix="server_auth")`. Fields: issuer, audience, algorithm, access_token_expire_minutes, refresh_token_expire_days, challenge_ttl_seconds, auto_create_admin, admin_email, admin_password, supported_wallet_algorithms.
30
+ - **`ChallengeStore`**: Protocol for challenge nonce storage. Default `InMemoryChallengeStore` uses dict with TTL. Replace with Redis/DB by registering a `@component` that implements the protocol.
31
+ - **`WalletVerifier`**: Verifies wallet signatures. Lazy-loads crypto backends (`cryptography` library) on first use.
32
+ - **`TokenIssuer`**: Generates RSA-2048 keypair at startup. Issues access tokens (configurable expiry) and refresh tokens. Exports JWKS for pico-client-auth.
33
+ - **Embedded mode**: pico-server-auth runs inside the same pico-boot process as your app controllers.
34
+ - **Standalone mode**: pico-server-auth runs as a dedicated auth service; other services fetch JWKS remotely.
35
+
36
+ ## Code Style
37
+
38
+ - Python 3.11+
39
+ - Async endpoints in controller, sync internals for crypto operations
40
+ - Use pico-ioc's `@component`, `@configured` decorators
41
+ - Use pico-fastapi's `@controller`, `@get`, `@post` decorators
42
+ - Error responses: JSON `{"detail": "..."}` via FastAPI `HTTPException`
43
+
44
+ ## Testing
45
+
46
+ - pytest + pytest-asyncio (mode=auto)
47
+ - RSA keypair fixture for token signing
48
+ - Mock ChallengeStore for controller tests
49
+ - httpx AsyncClient with ASGITransport for e2e tests
50
+
51
+ ## Boundaries
52
+
53
+ - Do not modify `_version.py`
54
+ - Public API is defined in `__init__.py` — ChallengeStore, InMemoryChallengeStore, ServerAuthSettings, TokenIssuer, WalletVerifier
55
+ - No direct dependency on pico-boot (uses entry point for auto-discovery)
56
+ - Depends on pico-client-auth only for `@allow_anonymous` decorator
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+
3
+ All notable changes to pico-server-auth will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2026-03-28
9
+
10
+ ### Added
11
+
12
+ - `AuthController` with `/auth/jwks`, `/auth/challenge`, `/auth/wallet`, and `/auth/login` endpoints.
13
+ - `ServerAuthSettings` configuration with `@configured(prefix="server_auth")`.
14
+ - `TokenIssuer` for RS256 JWT access and refresh token issuance.
15
+ - `WalletVerifier` with support for ML-DSA-65, Ed25519, and secp256k1 signature verification.
16
+ - `ChallengeStore` protocol with `InMemoryChallengeStore` default implementation.
17
+ - JWKS endpoint compatible with pico-client-auth token validation.
18
+ - Password-based admin login with configurable credentials.
19
+ - Auto-discovery via `pico_boot.modules` entry point.
20
+
21
+ [0.1.0]: https://github.com/dperezcabrera/pico-server-auth/releases/tag/v0.1.0
@@ -0,0 +1,34 @@
1
+ Read and follow ./AGENTS.md for project conventions.
2
+
3
+ ## Pico Ecosystem Context
4
+
5
+ pico-server-auth is an embeddable auth server module for pico-boot applications. It provides:
6
+ - JWT issuance (RS256) via `TokenIssuer`
7
+ - Wallet challenge/verify login (ML-DSA-65, Ed25519, secp256k1) via `WalletVerifier`
8
+ - Password-based admin login via `AuthController`
9
+ - JWKS endpoint for pico-client-auth token validation
10
+ - In-memory `ChallengeStore` with TTL expiry (replaceable via protocol)
11
+
12
+ It uses:
13
+ - `@component`, `@configured` from pico-ioc
14
+ - `@controller`, `@get`, `@post` from pico-fastapi
15
+ - `@allow_anonymous` from pico-client-auth
16
+ - Auto-discovered via `pico_boot.modules` entry point
17
+
18
+ ## Key Components
19
+
20
+ - **`ServerAuthSettings`**: `@configured(prefix="server_auth")` — issuer, audience, algorithm, TTLs, admin credentials, supported wallet algorithms
21
+ - **`AuthController`**: `@controller(prefix="/auth")` — endpoints: `/auth/jwks`, `/auth/challenge`, `/auth/wallet`, `/auth/login`
22
+ - **`TokenIssuer`**: `@component` — RSA key generation, JWT signing, JWKS export
23
+ - **`WalletVerifier`**: `@component` — signature verification for ML-DSA-65, Ed25519, secp256k1
24
+ - **`ChallengeStore`**: Protocol with `InMemoryChallengeStore` default (`@component(on_missing_selector=ChallengeStore)`)
25
+
26
+ ## Key Reminders
27
+
28
+ - **NEVER change `version_scheme`** in pyproject.toml. It MUST remain `"post-release"`.
29
+ - requires-python >= 3.11
30
+ - Commit messages: one line only
31
+ - Tokens issued here are compatible with pico-client-auth validation (same issuer/audience)
32
+ - `ChallengeStore` is a Protocol — users can replace with Redis/DB by registering their own `@component`
33
+ - `WalletVerifier` lazy-loads crypto backends to avoid hard dependencies
34
+ - `TokenIssuer` generates a fresh RSA keypair on startup (key ID: `pico-server-auth-1`)
@@ -0,0 +1,35 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, religion, or sexual identity
10
+ and orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to a positive environment:
15
+
16
+ * Using welcoming and inclusive language
17
+ * Being respectful of differing viewpoints and experiences
18
+ * Gracefully accepting constructive criticism
19
+ * Focusing on what is best for the community
20
+
21
+ Examples of unacceptable behavior:
22
+
23
+ * Trolling, insulting or derogatory comments, and personal or political attacks
24
+ * Public or private harassment
25
+ * Publishing others' private information without explicit permission
26
+ * Other conduct which could reasonably be considered inappropriate
27
+
28
+ ## Enforcement
29
+
30
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
31
+ reported to the project maintainer at **dperezcabrera@gmail.com**.
32
+
33
+ ## Attribution
34
+
35
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
@@ -0,0 +1,37 @@
1
+ # Contributing to pico-server-auth
2
+
3
+ ## Development setup
4
+
5
+ ```bash
6
+ git clone https://github.com/dperezcabrera/pico-server-auth.git
7
+ cd pico-server-auth
8
+ python -m venv .venv && source .venv/bin/activate
9
+ pip install -e ".[dev]"
10
+ ```
11
+
12
+ ## Running tests
13
+
14
+ ```bash
15
+ pytest tests/ -v
16
+ pytest --cov=pico_server_auth --cov-report=term-missing tests/
17
+ tox
18
+ ```
19
+
20
+ ## Linting
21
+
22
+ ```bash
23
+ ruff check src/ tests/
24
+ ruff format src/ tests/
25
+ ```
26
+
27
+ ## Code style
28
+
29
+ - Python 3.11+
30
+ - See AGENTS.md for conventions
31
+ - Single-line commit messages
32
+
33
+ ## What NOT to do
34
+
35
+ - Don't modify `_version.py` (auto-generated)
36
+ - Don't change `version_scheme` in pyproject.toml
37
+ - Don't add runtime dependencies without discussion
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 David Pérez Cabrera
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,5 @@
1
+ include README.md LICENSE CHANGELOG.md
2
+ recursive-include src *.py py.typed
3
+ recursive-include tests *.py
4
+ exclude .gitignore Dockerfile* docker-compose*.yml Makefile
5
+ prune build dist .tox .pytest_cache __pycache__
@@ -0,0 +1,169 @@
1
+ Metadata-Version: 2.4
2
+ Name: pico-server-auth
3
+ Version: 0.1.0
4
+ Summary: Embeddable auth server module for the pico ecosystem — JWT issuance, wallet login, JWKS endpoint
5
+ Author-email: David Perez Cabrera <dperezcabrera@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/dperezcabrera/pico-server-auth
8
+ Project-URL: Documentation, https://dperezcabrera.github.io/pico-server-auth/
9
+ Project-URL: Repository, https://github.com/dperezcabrera/pico-server-auth
10
+ Project-URL: Changelog, https://github.com/dperezcabrera/pico-server-auth/blob/main/CHANGELOG.md
11
+ Project-URL: Issue Tracker, https://github.com/dperezcabrera/pico-server-auth/issues
12
+ Keywords: auth,jwt,wallet,challenge-response,jwks,ml-dsa-65,ed25519,secp256k1,post-quantum,pico-ioc,pico-boot,dependency-injection
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Framework :: AsyncIO
16
+ Classifier: Typing :: Typed
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: License :: OSI Approved :: MIT License
23
+ Classifier: Operating System :: OS Independent
24
+ Requires-Python: >=3.11
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: pico-ioc[yaml]>=2.2.0
28
+ Requires-Dist: pico-boot>=0.1.0
29
+ Requires-Dist: pico-fastapi>=0.1.0
30
+ Requires-Dist: python-jose[cryptography]>=3.3.0
31
+ Requires-Dist: cryptography>=42.0.0
32
+ Requires-Dist: pydantic>=2.0.0
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
35
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
36
+ Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
37
+ Requires-Dist: ruff>=0.9.0; extra == "dev"
38
+ Requires-Dist: httpx; extra == "dev"
39
+ Dynamic: license-file
40
+
41
+ # pico-server-auth
42
+
43
+ [![PyPI](https://img.shields.io/pypi/v/pico-server-auth.svg)](https://pypi.org/project/pico-server-auth/)
44
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/dperezcabrera/pico-server-auth)
45
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
46
+ ![CI](https://github.com/dperezcabrera/pico-server-auth/actions/workflows/ci.yml/badge.svg)
47
+ [![codecov](https://codecov.io/gh/dperezcabrera/pico-server-auth/branch/main/graph/badge.svg)](https://codecov.io/gh/dperezcabrera/pico-server-auth)
48
+ [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=dperezcabrera_pico-server-auth&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=dperezcabrera_pico-server-auth)
49
+ [![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=dperezcabrera_pico-server-auth&metric=duplicated_lines_density)](https://sonarcloud.io/summary/new_code?id=dperezcabrera_pico-server-auth)
50
+ [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=dperezcabrera_pico-server-auth&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=dperezcabrera_pico-server-auth)
51
+ [![PyPI Downloads](https://static.pepy.tech/personalized-badge/pico-server-auth?period=monthly&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=Monthly+downloads)](https://pepy.tech/projects/pico-server-auth)
52
+ [![Docs](https://img.shields.io/badge/Docs-pico--server--auth-blue?style=flat&logo=readthedocs&logoColor=white)](https://dperezcabrera.github.io/pico-server-auth/)
53
+ [![Interactive Lab](https://img.shields.io/badge/Learn-online-green?style=flat&logo=python&logoColor=white)](https://dperezcabrera.github.io/pico-learn/)
54
+
55
+ Embeddable auth server module for the [pico-boot](https://github.com/dperezcabrera/pico-boot) ecosystem.
56
+
57
+ Issues JWT tokens, handles wallet challenge-response login, and exposes JWKS — all compatible with [pico-client-auth](https://github.com/dperezcabrera/pico-client-auth) validation.
58
+
59
+ ## Two deployment modes
60
+
61
+ **Embedded** — add to any pico-boot app, auth runs in the same process:
62
+
63
+ ```python
64
+ container = init(modules=["myapp", "pico_server_auth"], config=config)
65
+ # /auth/jwks, /auth/challenge, /auth/wallet, /auth/login — all available
66
+ # pico-client-auth validates tokens from the same JWKS
67
+ ```
68
+
69
+ **Standalone** — deploy as a separate auth service (like pico-auth):
70
+
71
+ ```python
72
+ container = init(modules=["pico_server_auth"], config=config)
73
+ app = container.get(FastAPI)
74
+ # Other services point pico-client-auth JWKS to this service's /auth/jwks
75
+ ```
76
+
77
+ ## Endpoints
78
+
79
+ ```
80
+ GET /auth/jwks JWKS public keys (pico-client-auth fetches this)
81
+ POST /auth/challenge Request nonce for wallet login
82
+ POST /auth/wallet Verify wallet signature, issue JWT
83
+ POST /auth/login Password login (admin bootstrap)
84
+ ```
85
+
86
+ ## Wallet login flow
87
+
88
+ ```
89
+ Client pico-server-auth
90
+ │ │
91
+ │ POST /auth/challenge │
92
+ │ { address: "0x..." } │
93
+ │───────────────────────────>│
94
+ │ { challenge: "<nonce>" } │
95
+ │<───────────────────────────│
96
+ │ │
97
+ │ sign(nonce) with wallet │
98
+ │ │
99
+ │ POST /auth/wallet │
100
+ │ { address, public_key, │
101
+ │ signature, challenge, │
102
+ │ algorithm: "ML-DSA-65" } │
103
+ │───────────────────────────>│
104
+ │ { access_token, address } │
105
+ │<───────────────────────────│
106
+ ```
107
+
108
+ ## Supported wallet algorithms
109
+
110
+ | Algorithm | Type | Library |
111
+ |-----------|------|---------|
112
+ | ML-DSA-65 | Post-quantum lattice (FIPS 204) | `cryptography` |
113
+ | Ed25519 | Edwards curve | `cryptography` |
114
+ | secp256k1 | Elliptic curve (ECDSA) | `cryptography` |
115
+
116
+ ## Compatibility with pico-client-auth
117
+
118
+ Tokens issued by pico-server-auth are standard JWT (RS256). pico-client-auth validates them by fetching JWKS from the `/auth/jwks` endpoint.
119
+
120
+ **Same process**: pico-client-auth discovers the JWKS endpoint automatically (same FastAPI app).
121
+
122
+ **Separate processes**: configure pico-client-auth to point to the server:
123
+
124
+ ```yaml
125
+ auth_client:
126
+ issuer: "http://auth-server:8100"
127
+ audience: "pico"
128
+ # JWKS fetched from http://auth-server:8100/auth/jwks
129
+ ```
130
+
131
+ ## Challenge store
132
+
133
+ By default, challenges are stored in memory with TTL expiry. For multi-instance deployments, register a custom `ChallengeStore` component:
134
+
135
+ ```python
136
+ @component
137
+ class RedisChallengeStore:
138
+ async def create(self, address: str) -> str: ...
139
+ async def validate(self, address: str, nonce: str) -> bool: ...
140
+ async def cleanup(self) -> int: ...
141
+ ```
142
+
143
+ The in-memory default is replaced automatically via `on_missing_selector`.
144
+
145
+ ## Configuration
146
+
147
+ ```yaml
148
+ server_auth:
149
+ issuer: "http://localhost:8100"
150
+ audience: "pico"
151
+ algorithm: "RS256"
152
+ access_token_expire_minutes: 15
153
+ challenge_ttl_seconds: 60
154
+ supported_wallet_algorithms:
155
+ - "ML-DSA-65"
156
+ - "Ed25519"
157
+ - "secp256k1"
158
+ ```
159
+
160
+ ## Stack
161
+
162
+ - [pico-ioc](https://github.com/dperezcabrera/pico-ioc) — dependency injection
163
+ - [pico-boot](https://github.com/dperezcabrera/pico-boot) — auto-discovery
164
+ - [pico-fastapi](https://github.com/dperezcabrera/pico-fastapi) — controllers
165
+ - [pico-client-auth](https://github.com/dperezcabrera/pico-client-auth) — token validation
166
+
167
+ ## License
168
+
169
+ MIT