Skip to content

Commit 8dd7591

Browse files
authored
Merge pull request #1 from feteu/develop
Develop
2 parents c7c8ea5 + 261744e commit 8dd7591

26 files changed

+2900
-0
lines changed

.github/workflows/build.yaml

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Build Python 🐍 distribution 📦
2+
3+
on: workflow_call
4+
5+
jobs:
6+
7+
build:
8+
name: Build the Magic Python 🧙‍♂️ Distribution 📦
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- uses: actions/checkout@v4
13+
with:
14+
persist-credentials: false
15+
- name: Set up the Python Wizardry 🧙‍♂️
16+
uses: actions/setup-python@v5
17+
with:
18+
python-version: "3.13"
19+
- name: Install the Build Potion 🧪
20+
run: |
21+
pip install build
22+
- name: Concoct the Binary Wheel and Source Tarball 🧙‍♀️
23+
run: |
24+
python -m build
25+
- name: Store the Magical Packages 🧳
26+
uses: actions/upload-artifact@v4
27+
with:
28+
name: python-package-distributions
29+
path: dist/

.github/workflows/publish-pypi.yaml

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: Publish Python 🐍 distribution 📦 to PyPI
2+
3+
on:
4+
workflow_dispatch:
5+
6+
jobs:
7+
build:
8+
uses: ./.github/workflows/build.yaml
9+
10+
publish-to-pypi:
11+
name: Teleport Python 🐍 Distribution 📦 to PyPI
12+
needs: build
13+
runs-on: ubuntu-latest
14+
environment:
15+
name: pypi
16+
url: https://pypi.org/p/asgi-claim-validator
17+
permissions:
18+
id-token: write
19+
20+
steps:
21+
- name: Summon the Distribution Artifacts 🧙‍♂️
22+
uses: actions/download-artifact@v4
23+
with:
24+
name: python-package-distributions
25+
path: dist/
26+
- name: Cast the Publish Spell 📦 to PyPI
27+
uses: pypa/gh-action-pypi-publish@67339c736fd9354cd4f8cb0b744f2b82a74b5c70
28+
29+
github-release:
30+
name: Enchant the Python 🐍 Distribution 📦 with Sigstore and Upload to GitHub Release
31+
needs: publish-to-pypi
32+
runs-on: ubuntu-latest
33+
34+
permissions:
35+
contents: write
36+
id-token: write
37+
38+
steps:
39+
- name: Summon the Distribution Artifacts 🧙‍♂️
40+
uses: actions/download-artifact@v4
41+
with:
42+
name: python-package-distributions
43+
path: dist/
44+
- name: Enchant the Artifacts with Sigstore ✨
45+
uses: sigstore/gh-action-sigstore-python@f514d46b907ebcd5bedc05145c03b69c1edd8b46
46+
with:
47+
inputs: >-
48+
./dist/*.tar.gz
49+
./dist/*.whl
50+
- name: Create the GitHub Release 🎉
51+
env:
52+
GITHUB_TOKEN: ${{ github.token }}
53+
run: |
54+
gh release create "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --notes ""
55+
- name: Upload the Enchanted Artifacts to GitHub Release 🧳
56+
env:
57+
GITHUB_TOKEN: ${{ github.token }}
58+
run: |
59+
gh release upload "$GITHUB_REF_NAME" dist/** --repo "$GITHUB_REPOSITORY"
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Publish Python 🐍 distribution 📦 to TestPyPI
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
jobs:
9+
build:
10+
uses: ./.github/workflows/build.yaml
11+
12+
publish-to-testpypi:
13+
name: Teleport Python 🐍 Distribution 📦 to TestPyPI
14+
needs: build
15+
runs-on: ubuntu-latest
16+
environment:
17+
name: testpypi
18+
url: https://test.pypi.org/p/asgi-claim-validator
19+
permissions:
20+
id-token: write
21+
22+
steps:
23+
- name: Summon the Distribution Artifacts 🧙‍♂️
24+
uses: actions/download-artifact@v4
25+
with:
26+
name: python-package-distributions
27+
path: dist/
28+
- name: Cast the Publish Spell 📦 to TestPyPI
29+
uses: pypa/gh-action-pypi-publish@67339c736fd9354cd4f8cb0b744f2b82a74b5c70
30+
with:
31+
repository-url: https://test.pypi.org/legacy/

.github/workflows/test.yaml

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
on:
2+
pull_request:
3+
push:
4+
branches:
5+
- main
6+
7+
jobs:
8+
test:
9+
runs-on: ubuntu-latest
10+
strategy:
11+
fail-fast: false
12+
matrix:
13+
python-version:
14+
- 3.11
15+
- 3.12
16+
- 3.13
17+
steps:
18+
- uses: actions/checkout@v3
19+
- uses: actions/setup-python@v5
20+
with:
21+
python-version: "${{ matrix.python-version }}"
22+
- name: Create a Python Wonderland 🐍✨
23+
run: |
24+
python -m venv .venv
25+
source .venv/bin/activate
26+
- name: Pimp My Pip 🚀🎩
27+
run: |
28+
source .venv/bin/activate
29+
pip install --upgrade pip
30+
- name: Dependency Party 🎉📦
31+
run: |
32+
source .venv/bin/activate
33+
pip install poetry
34+
rm poetry.lock
35+
poetry install --no-interaction --no-root
36+
- name: Install the app 📲🚀
37+
run: |
38+
source .venv/bin/activate
39+
poetry install --no-interaction
40+
- name: Test Fest 🎈✅
41+
run: |
42+
source .venv/bin/activate
43+
poetry run pytest -c pytest.ini

CONTRIBUTING.md

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Contributing to ASGI Claim Validator
2+
3+
Thanks for thinking about contributing to ASGI Request Duration! I welcome your help and can't wait to see what you'll bring to the table.
4+
5+
## How to Contribute
6+
7+
### Reporting Bugs
8+
9+
Found a bug? Report it by opening an issue on my [GitHub Issues](https://github.com/feteu/asgi-claim-validator/issues) page. The more details, the better!
10+
11+
### Feature Requests
12+
13+
Got a brilliant idea for a new feature? Open an issue on the [GitHub Issues](https://github.com/feteu/asgi-claim-validator/issues) page. Let's collaborate to enhance this project together.
14+
15+
### Submitting Changes
16+
17+
1. **Fork it**: Click the "Fork" button.
18+
2. **Clone it**: Clone your fork.
19+
```sh
20+
git clone https://github.com/your-username/asgi-claim-validator.git
21+
```
22+
3. **Branch it**: Create a new branch.
23+
```sh
24+
git checkout -b my-awesome-feature
25+
```
26+
4. **Change it**: Make your magic happen.
27+
5. **Commit it**: Commit with style.
28+
```sh
29+
git commit -m "My awesome changes"
30+
```
31+
6. **Push it**: Push to your fork.
32+
```sh
33+
git push origin my-awesome-feature
34+
```
35+
7. **Pull it**: Open a pull request. Describe your awesomeness.
36+
37+
### Setting Up the Development Environment
38+
39+
1. **Clone the repository**:
40+
```sh
41+
git clone https://github.com/feteu/asgi-claim-validator.git
42+
cd asgi-claim-validator
43+
```
44+
2. **Install dependencies using Poetry**:
45+
```sh
46+
poetry install
47+
```
48+
49+
### Running Tests
50+
51+
Run the tests using `pytest`:
52+
```sh
53+
poetry run pytest
54+
```
55+
56+
### Code Style
57+
58+
Maintain a clean and consistent code style. Adhere to the existing conventions. If you notice any errors or areas for improvement, please correct them or let me know. I'm always eager to learn and improve.
59+
60+
### Documentation
61+
62+
Update the docs if you change or add something. Keep everyone in the loop.
63+
64+
## Need Help?
65+
66+
Open an issue on the [GitHub Issues](https://github.com/feteu/asgi-claim-validator/issues) page. I'll do my best to help.
67+
68+
## Reviewing Pull Requests
69+
70+
I'll review your pull request ASAP. Thanks for your patience!
71+
72+
## Acknowledgements
73+
74+
Thanks for contributing! Your support makes this project rock.

COPYRIGHT

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
asgi-claim-validator
2+
Copyright (C) 2024 Fabio Greco
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program. If not, see <https://www.gnu.org/licenses/>.

README.md

+121
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,123 @@
1+
[![PyPI - License](https://img.shields.io/pypi/l/asgi-claim-validator)](https://www.gnu.org/licenses/gpl-3.0)
2+
[![PyPI - Version](https://img.shields.io/pypi/v/asgi-claim-validator.svg)](https://pypi.org/project/asgi-claim-validator/)
3+
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/asgi-claim-validator)](https://pypi.org/project/asgi-claim-validator/)
4+
[![PyPI - Status](https://img.shields.io/pypi/status/asgi-claim-validator)](https://pypi.org/project/asgi-claim-validator/)
5+
[![Dependencies](https://img.shields.io/librariesio/release/pypi/asgi-claim-validator)](https://libraries.io/pypi/asgi-claim-validator)
6+
[![Last Commit](https://img.shields.io/github/last-commit/feteu/asgi-claim-validator)](https://github.com/feteu/asgi-claim-validator/commits/main)
7+
[![Build Status build/testpypi](https://img.shields.io/github/actions/workflow/status/feteu/asgi-claim-validator/publish-testpypi.yaml?label=publish-testpypi)](https://github.com/feteu/asgi-claim-validator/actions/workflows/publish-testpypi.yaml)
8+
[![Build Status build/pypi](https://img.shields.io/github/actions/workflow/status/feteu/asgi-claim-validator/publish-pypi.yaml?label=publish-pypi)](https://github.com/feteu/asgi-claim-validator/actions/workflows/publish-pypi.yaml)
9+
[![Build Status test](https://img.shields.io/github/actions/workflow/status/feteu/asgi-claim-validator/test.yaml?label=test)](https://github.com/feteu/asgi-claim-validator/actions/workflows/test.yaml)
10+
111
# asgi-claim-validator
12+
213
A focused ASGI middleware for validating additional claims within JWT tokens to enhance token-based workflows.
14+
15+
## Overview
16+
17+
`asgi-claim-validator` is an ASGI middleware designed to validate additional claims within JWT tokens. Built in addition to the default JWT verification implementation of Connexion, it enhances token-based workflows by ensuring that specific claims are present and meet certain criteria before allowing access to protected endpoints. This middleware allows consumers to validate claims on an endpoint/method level and is compatible with popular ASGI frameworks such as Starlette, FastAPI, and Connexion.
18+
19+
## Features
20+
21+
- **Claim Validation**: Validate specific claims within JWT tokens, such as `sub`, `iss`, `aud`, `exp`, `iat`, and `nbf`.
22+
- **Customizable Claims**: Define essential claims, allowed values, and whether blank values are permitted.
23+
- **Path and Method Filtering**: Apply claim validation to specific paths and HTTP methods.
24+
- **Exception Handling**: Integrate with custom exception handlers to provide meaningful error responses.
25+
- **Logging**: Log validation errors for debugging and monitoring purposes.
26+
27+
## Installation
28+
29+
Install the package using pip:
30+
31+
```sh
32+
pip install asgi-claim-validator
33+
```
34+
35+
## Usage
36+
37+
### Basic Usage
38+
39+
Here's an example of how to use `asgi-claim-validator` with Starlette:
40+
41+
```python
42+
from starlette.applications import Starlette
43+
from starlette.requests import Request
44+
from starlette.responses import JSONResponse
45+
from starlette.routing import Route
46+
from asgi_claim_validator import ClaimValidatorMiddleware
47+
48+
async def secured_endpoint(request: Request) -> JSONResponse:
49+
return JSONResponse({"message": "secured"})
50+
51+
app = Starlette(routes=[
52+
Route("/secured", secured_endpoint, methods=["GET"]),
53+
])
54+
55+
app.add_middleware(
56+
ClaimValidatorMiddleware,
57+
claims_callable=lambda: {
58+
"sub": "admin",
59+
"iss": "https://example.com",
60+
},
61+
secured={
62+
"^/secured$": {
63+
"GET": {
64+
"sub": {
65+
"essential": True,
66+
"allow_blank": False,
67+
"values": ["admin"],
68+
},
69+
"iss": {
70+
"essential": True,
71+
"allow_blank": False,
72+
"values": ["https://example.com"],
73+
},
74+
},
75+
}
76+
},
77+
)
78+
```
79+
80+
## Advanced Usage
81+
82+
### Custom Exception Handlers
83+
84+
Integrate `asgi-claim-validator` with custom exception handlers to provide meaningful error responses. Below are examples for Starlette and Connexion. Refer to the specific framework examples in the [examples](examples) directory for detailed implementation.
85+
86+
### Middleware Configuration
87+
88+
Configure the middleware with the following options:
89+
90+
- **claims_callable**: A callable that returns the JWT claims to be validated.
91+
- **secured**: A dictionary defining the paths and methods that require claim validation.
92+
- **skipped**: A dictionary defining the paths and methods to be excluded from claim validation.
93+
- **raise_on_unspecified_path**: Raise an exception if the path is not specified in the `secured` or `skipped` dictionaries.
94+
- **raise_on_unspecified_method**: Raise an exception if the method is not specified for a secured path.
95+
96+
### Claim Validation Options
97+
98+
Configure claims with the following options:
99+
100+
- **essential**: Indicates if the claim is essential (default: `False`).
101+
- **allow_blank**: Indicates if blank values are allowed (default: `True`).
102+
- **values**: A list of allowed values for the claim.
103+
104+
## Examples
105+
106+
### Starlette Example
107+
Refer to the [app.py](examples/starlette/simple/app.py) file for a complete example using Starlette.
108+
109+
### Connexion Example
110+
Refer to the [app.py](examples/connexion/simple/app.py) file for a complete example using Connexion.
111+
112+
## Testing
113+
Run the tests using `pytest`:
114+
115+
```sh
116+
poetry run pytest
117+
```
118+
119+
## Contributing
120+
Contributions are welcome! Please refer to the [CONTRIBUTING.md](CONTRIBUTING.md) file for guidelines on how to contribute to this project.
121+
122+
## License
123+
This project is licensed under the GNU GPLv3 License. See the [LICENSE](LICENSE) file for more details.

0 commit comments

Comments
 (0)