Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.0.0 #1

Merged
merged 56 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
765631f
Add GitHub Actions workflows for building, testing, and publishing Py…
feteu Dec 28, 2024
98be4fe
Add initial project structure with contributing guidelines, copyright…
feteu Dec 28, 2024
81198b9
Add joserfc dependency to pyproject.toml
feteu Dec 28, 2024
66cd284
WIP: Add ClaimValidatorMiddleware for JWT claim validation in ASGI ap…
feteu Dec 28, 2024
95e3862
Update Python version constraint and refine development dependencies …
feteu Dec 29, 2024
9873023
Refactor example Starlette application with updated API routes and en…
feteu Dec 29, 2024
1b1508e
Add Connexion API example with multiple endpoints and OpenAPI specifi…
feteu Dec 29, 2024
8cb6c3a
Add exceptions and middleware to asgi_claim_validator module
feteu Dec 29, 2024
12641ea
Add constants for claim validation configuration in asgi_claim_validator
feteu Dec 29, 2024
0eb1fce
Add custom exceptions for claim validation errors in asgi_claim_valid…
feteu Dec 29, 2024
6bd525b
Enhance ClaimValidatorMiddleware with detailed configuration options …
feteu Dec 29, 2024
c91488d
Refactor Connexion and Starlette examples by removing unused endpoint…
feteu Dec 29, 2024
97a4d99
Refactor ClaimValidatorMiddleware to compile secured and skipped path…
feteu Dec 29, 2024
b2ba254
Refactor ClaimValidatorMiddleware to use a set for compiled skipped p…
feteu Dec 29, 2024
c904eb9
Enhance connexion_simple example by updating HTTP method for UI endpo…
feteu Dec 29, 2024
4466a48
Improve error handling in ClaimValidatorMiddleware by using claims_re…
feteu Dec 29, 2024
33cdd35
Update starlette dependency to version 0.45.2 and adjust Python versi…
feteu Jan 4, 2025
7f0960f
Add type definitions and validation decorator for claims handling
feteu Jan 4, 2025
f54eff5
Refactor connexion_simple example to enhance claim validation configu…
feteu Jan 4, 2025
8f55929
Update workflow URLs for PyPI and TestPyPI to reflect new package nam…
feteu Jan 4, 2025
4bc2983
Update anyio dependency to version 4.8.0 and add jsonschema to projec…
feteu Jan 5, 2025
3439a6d
Add new exception classes for invalid secured and skipped configurations
feteu Jan 5, 2025
a13cfa5
Add JSON schema definitions for secured and skipped configurations
feteu Jan 5, 2025
e6dda77
Add decorators for secured and skipped configuration validation with …
feteu Jan 5, 2025
9acebb7
Add validation decorators for secured and skipped claims in middleware
feteu Jan 5, 2025
6347a4b
Refactor HTTP method constants and update validation schemas for secu…
feteu Jan 5, 2025
6655855
Update request method check in ClaimValidatorMiddleware to support de…
feteu Jan 5, 2025
e9a9f51
Update secured JSON schema to include all HTTP methods in pattern val…
feteu Jan 5, 2025
81dad00
Update secured and skipped constants and JSON schemas to support all …
feteu Jan 5, 2025
1e06d72
Fix formatting of HTTP methods list in constants.py
feteu Jan 5, 2025
f746c6d
Fix formatting and structure of HTTP method constants in constants.py
feteu Jan 5, 2025
f7c04ff
renamed example files
feteu Jan 5, 2025
cd058d3
renamed examples
feteu Jan 5, 2025
e68d31e
Refactor claim validator error handling in app.py
feteu Jan 5, 2025
314ee20
Fix validation calls in decorators.py to use correct instance validat…
feteu Jan 5, 2025
66e2b23
Add regex group for HTTP methods in constants.py
feteu Jan 5, 2025
2822ed6
Refactor decorators to use instance attributes for claims and secured…
feteu Jan 5, 2025
fcd2db3
Add return statement in ClaimValidatorMiddleware to ensure proper flow
feteu Jan 5, 2025
08109de
Add pytest-asyncio support and implement tests for claim validation e…
feteu Jan 6, 2025
9610329
Rename API endpoint to /api/1/blocked and update response message
feteu Jan 6, 2025
75eec0d
Rename 'claims' to 'claims_callable' in configuration for clarity
feteu Jan 6, 2025
f920bd2
Reorganize configuration to move 'claims_callable' and restore 'skipp…
feteu Jan 6, 2025
3844277
Fix attribute name in validate_secured decorator for consistency
feteu Jan 6, 2025
ed027b3
Update pytest configuration for improved verbosity and formatting
feteu Jan 6, 2025
54dfbe0
Reorder unauthenticated request check for improved clarity in ClaimVa…
feteu Jan 6, 2025
0fa511c
Add HEAD method support for secured and blocked endpoints; enhance te…
feteu Jan 6, 2025
2ba7aa9
Rename 'description' attribute to 'detail' in ClaimValidatorException…
feteu Jan 7, 2025
e0e5024
Add custom error handler for ClaimValidatorException in middleware tests
feteu Jan 7, 2025
efa6761
Refactor tests for claims validation: introduce TestClass for better …
feteu Jan 12, 2025
002f75b
Reorganize imports in test files for improved clarity and consistency
feteu Jan 12, 2025
c91e659
Refactor regex imports and usage for consistency; update logging init…
feteu Jan 12, 2025
5abb0b5
Bump dependencies and update project version to 1.0.0
feteu Jan 12, 2025
7a28988
Update logging level import for consistency in ClaimValidatorMiddleware
feteu Jan 12, 2025
833112a
Refactor import order and update time function usage for consistency …
feteu Jan 12, 2025
c49c872
Update README.md to include badges, usage examples, and detailed conf…
feteu Jan 12, 2025
261744e
Fix formatting of regex group definition in constants.py for improved…
feteu Jan 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Build Python 🐍 distribution 📦

on: workflow_call

jobs:

build:
name: Build the Magic Python 🧙‍♂️ Distribution 📦
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up the Python Wizardry 🧙‍♂️
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install the Build Potion 🧪
run: |
pip install build
- name: Concoct the Binary Wheel and Source Tarball 🧙‍♀️
run: |
python -m build
- name: Store the Magical Packages 🧳
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/
59 changes: 59 additions & 0 deletions .github/workflows/publish-pypi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Publish Python 🐍 distribution 📦 to PyPI

on:
workflow_dispatch:

jobs:
build:
uses: ./.github/workflows/build.yaml

publish-to-pypi:
name: Teleport Python 🐍 Distribution 📦 to PyPI
needs: build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/asgi-claim-validator
permissions:
id-token: write

steps:
- name: Summon the Distribution Artifacts 🧙‍♂️
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Cast the Publish Spell 📦 to PyPI
uses: pypa/gh-action-pypi-publish@67339c736fd9354cd4f8cb0b744f2b82a74b5c70

github-release:
name: Enchant the Python 🐍 Distribution 📦 with Sigstore and Upload to GitHub Release
needs: publish-to-pypi
runs-on: ubuntu-latest

permissions:
contents: write
id-token: write

steps:
- name: Summon the Distribution Artifacts 🧙‍♂️
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Enchant the Artifacts with Sigstore ✨
uses: sigstore/gh-action-sigstore-python@f514d46b907ebcd5bedc05145c03b69c1edd8b46
with:
inputs: >-
./dist/*.tar.gz
./dist/*.whl
- name: Create the GitHub Release 🎉
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
gh release create "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --notes ""
- name: Upload the Enchanted Artifacts to GitHub Release 🧳
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
gh release upload "$GITHUB_REF_NAME" dist/** --repo "$GITHUB_REPOSITORY"
31 changes: 31 additions & 0 deletions .github/workflows/publish-testpypi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Publish Python 🐍 distribution 📦 to TestPyPI

on:
push:
branches:
- main

jobs:
build:
uses: ./.github/workflows/build.yaml

publish-to-testpypi:
name: Teleport Python 🐍 Distribution 📦 to TestPyPI
needs: build
runs-on: ubuntu-latest
environment:
name: testpypi
url: https://test.pypi.org/p/asgi-claim-validator
permissions:
id-token: write

steps:
- name: Summon the Distribution Artifacts 🧙‍♂️
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Cast the Publish Spell 📦 to TestPyPI
uses: pypa/gh-action-pypi-publish@67339c736fd9354cd4f8cb0b744f2b82a74b5c70
with:
repository-url: https://test.pypi.org/legacy/
43 changes: 43 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
on:
pull_request:
push:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version:
- 3.11
- 3.12
- 3.13
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v5
with:
python-version: "${{ matrix.python-version }}"
- name: Create a Python Wonderland 🐍✨
run: |
python -m venv .venv
source .venv/bin/activate
- name: Pimp My Pip 🚀🎩
run: |
source .venv/bin/activate
pip install --upgrade pip
- name: Dependency Party 🎉📦
run: |
source .venv/bin/activate
pip install poetry
rm poetry.lock
poetry install --no-interaction --no-root
- name: Install the app 📲🚀
run: |
source .venv/bin/activate
poetry install --no-interaction
- name: Test Fest 🎈✅
run: |
source .venv/bin/activate
poetry run pytest -c pytest.ini
74 changes: 74 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Contributing to ASGI Claim Validator

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.

## How to Contribute

### Reporting Bugs

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!

### Feature Requests

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.

### Submitting Changes

1. **Fork it**: Click the "Fork" button.
2. **Clone it**: Clone your fork.
```sh
git clone https://github.com/your-username/asgi-claim-validator.git
```
3. **Branch it**: Create a new branch.
```sh
git checkout -b my-awesome-feature
```
4. **Change it**: Make your magic happen.
5. **Commit it**: Commit with style.
```sh
git commit -m "My awesome changes"
```
6. **Push it**: Push to your fork.
```sh
git push origin my-awesome-feature
```
7. **Pull it**: Open a pull request. Describe your awesomeness.

### Setting Up the Development Environment

1. **Clone the repository**:
```sh
git clone https://github.com/feteu/asgi-claim-validator.git
cd asgi-claim-validator
```
2. **Install dependencies using Poetry**:
```sh
poetry install
```

### Running Tests

Run the tests using `pytest`:
```sh
poetry run pytest
```

### Code Style

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.

### Documentation

Update the docs if you change or add something. Keep everyone in the loop.

## Need Help?

Open an issue on the [GitHub Issues](https://github.com/feteu/asgi-claim-validator/issues) page. I'll do my best to help.

## Reviewing Pull Requests

I'll review your pull request ASAP. Thanks for your patience!

## Acknowledgements

Thanks for contributing! Your support makes this project rock.
15 changes: 15 additions & 0 deletions COPYRIGHT
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
asgi-claim-validator
Copyright (C) 2024 Fabio Greco

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
121 changes: 121 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,123 @@
[![PyPI - License](https://img.shields.io/pypi/l/asgi-claim-validator)](https://www.gnu.org/licenses/gpl-3.0)
[![PyPI - Version](https://img.shields.io/pypi/v/asgi-claim-validator.svg)](https://pypi.org/project/asgi-claim-validator/)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/asgi-claim-validator)](https://pypi.org/project/asgi-claim-validator/)
[![PyPI - Status](https://img.shields.io/pypi/status/asgi-claim-validator)](https://pypi.org/project/asgi-claim-validator/)
[![Dependencies](https://img.shields.io/librariesio/release/pypi/asgi-claim-validator)](https://libraries.io/pypi/asgi-claim-validator)
[![Last Commit](https://img.shields.io/github/last-commit/feteu/asgi-claim-validator)](https://github.com/feteu/asgi-claim-validator/commits/main)
[![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)
[![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)
[![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)

# asgi-claim-validator

A focused ASGI middleware for validating additional claims within JWT tokens to enhance token-based workflows.

## Overview

`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.

## Features

- **Claim Validation**: Validate specific claims within JWT tokens, such as `sub`, `iss`, `aud`, `exp`, `iat`, and `nbf`.
- **Customizable Claims**: Define essential claims, allowed values, and whether blank values are permitted.
- **Path and Method Filtering**: Apply claim validation to specific paths and HTTP methods.
- **Exception Handling**: Integrate with custom exception handlers to provide meaningful error responses.
- **Logging**: Log validation errors for debugging and monitoring purposes.

## Installation

Install the package using pip:

```sh
pip install asgi-claim-validator
```

## Usage

### Basic Usage

Here's an example of how to use `asgi-claim-validator` with Starlette:

```python
from starlette.applications import Starlette
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette.routing import Route
from asgi_claim_validator import ClaimValidatorMiddleware

async def secured_endpoint(request: Request) -> JSONResponse:
return JSONResponse({"message": "secured"})

app = Starlette(routes=[
Route("/secured", secured_endpoint, methods=["GET"]),
])

app.add_middleware(
ClaimValidatorMiddleware,
claims_callable=lambda: {
"sub": "admin",
"iss": "https://example.com",
},
secured={
"^/secured$": {
"GET": {
"sub": {
"essential": True,
"allow_blank": False,
"values": ["admin"],
},
"iss": {
"essential": True,
"allow_blank": False,
"values": ["https://example.com"],
},
},
}
},
)
```

## Advanced Usage

### Custom Exception Handlers

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.

### Middleware Configuration

Configure the middleware with the following options:

- **claims_callable**: A callable that returns the JWT claims to be validated.
- **secured**: A dictionary defining the paths and methods that require claim validation.
- **skipped**: A dictionary defining the paths and methods to be excluded from claim validation.
- **raise_on_unspecified_path**: Raise an exception if the path is not specified in the `secured` or `skipped` dictionaries.
- **raise_on_unspecified_method**: Raise an exception if the method is not specified for a secured path.

### Claim Validation Options

Configure claims with the following options:

- **essential**: Indicates if the claim is essential (default: `False`).
- **allow_blank**: Indicates if blank values are allowed (default: `True`).
- **values**: A list of allowed values for the claim.

## Examples

### Starlette Example
Refer to the [app.py](examples/starlette/simple/app.py) file for a complete example using Starlette.

### Connexion Example
Refer to the [app.py](examples/connexion/simple/app.py) file for a complete example using Connexion.

## Testing
Run the tests using `pytest`:

```sh
poetry run pytest
```

## Contributing
Contributions are welcome! Please refer to the [CONTRIBUTING.md](CONTRIBUTING.md) file for guidelines on how to contribute to this project.

## License
This project is licensed under the GNU GPLv3 License. See the [LICENSE](LICENSE) file for more details.
Loading
Loading