Skip to content

Repository pre-publish sanitizations #6

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

Merged
merged 36 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
38397b0
Sync package metadata with the repository
ArtyomVancyan Jun 30, 2023
4cb60f4
GH-4: Add the common README sections
ArtyomVancyan Jun 30, 2023
42308d0
GH-4: Move the demo app to `examples` dir
ArtyomVancyan Jul 1, 2023
869b8bc
GH-4: Rearrange the config and router
ArtyomVancyan Jul 1, 2023
ff15ebf
GH-4: Create a README for basic run
ArtyomVancyan Jul 1, 2023
d21057b
Create a common ignore list
ArtyomVancyan Jun 29, 2023
4899131
GH-4: Fix the link
ArtyomVancyan Jul 2, 2023
9ddee23
GH-4: Add code snippets
ArtyomVancyan Jul 2, 2023
5509c7d
GH-4: Add brief descriptions for each section
ArtyomVancyan Jul 3, 2023
970adba
GH-5: Specify max dependency versions for Python>=3.6
ArtyomVancyan Jul 4, 2023
2f8e2dd
GH-5: Create `tests` package and `requirements.txt` for environment
ArtyomVancyan Jul 4, 2023
506fe43
GH-5: Setup `tox` environment configs
ArtyomVancyan Jul 4, 2023
e57f7fb
GH-5: Setup CI for `tox`
ArtyomVancyan Jul 4, 2023
51ac549
GH-5: Create a basic test-case
ArtyomVancyan Jul 4, 2023
1862d30
GH-5: Fix `fastapi` version range
ArtyomVancyan Jul 4, 2023
772c907
GH-5: Downgrade the `httpx` version for test env
ArtyomVancyan Jul 4, 2023
3d8c544
Fix typing of the `jwt_expires` argument
ArtyomVancyan Jul 5, 2023
973fc10
Get `Authorization` from headers before reading from cookies
ArtyomVancyan Jul 5, 2023
39076c5
Normalize imports by coding style
ArtyomVancyan Jul 5, 2023
829d97a
GH-4: Add the common badges
ArtyomVancyan Jul 6, 2023
5d6d560
Update the development status
ArtyomVancyan Jul 6, 2023
2d92892
Setup a CI for publishing the package
ArtyomVancyan Jul 6, 2023
41106e7
GH-4: Add two more features to be implemented
ArtyomVancyan Jul 7, 2023
61c47f7
Make the logout router synchronous
ArtyomVancyan Jul 8, 2023
ad3abe5
Fix the `exp` when creating a JWT
ArtyomVancyan Jul 8, 2023
bd22f08
Add `trio` as a dev dependency for tests
ArtyomVancyan Jul 8, 2023
cf57ab6
GH-5: Ignore `TrioDeprecationWarning`
ArtyomVancyan Jul 8, 2023
354035a
GH-5: Use `trio>=0.19.0` for Python 3.6 support
ArtyomVancyan Jul 8, 2023
0e34059
GH-5: Use `httpx.AsyncClient` for testing async routes
ArtyomVancyan Jul 9, 2023
8f25cd9
GH-5: Add basic configs of a client
ArtyomVancyan Jul 9, 2023
4e0504f
GH-5: Add a sample test case for '/auth' route
ArtyomVancyan Jul 9, 2023
49c938a
GH-5: Add 'appengine-python-standard' in dev dependency list
ArtyomVancyan Jul 11, 2023
72ddf3c
GH-5: Test backend initialization with all available implementations
ArtyomVancyan Jul 11, 2023
2254c78
GH-5: Create a fixture for getting the list of available backends
ArtyomVancyan Jul 13, 2023
f642d74
GH-5: Simplify the testing of clients with all backends
ArtyomVancyan Jul 13, 2023
5be639a
Alpha release: Pilot open-source version
ArtyomVancyan Jul 13, 2023
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
28 changes: 28 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Publish to PyPI

on:
release:
types: [ published ]

jobs:
deploy:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
55 changes: 55 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: tests

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
test:
runs-on: ${{ matrix.os || 'ubuntu-latest' }}
strategy:
matrix:
include:
- python: "3.6"
env: py36-fastapi68
os: ubuntu-20.04 # 3.6 is not available on ubuntu-20.04
- python: "3.8"
env: py38-fastapi68
- python: "3.10"
env: py310-fastapi68
- python: "3.11"
env: py311-fastapi68

- python: "3.7"
env: py37-fastapi84
- python: "3.9"
env: py39-fastapi84
- python: "3.10"
env: py310-fastapi84
- python: "3.11"
env: py311-fastapi84

- python: "3.7"
env: py37-fastapi99
- python: "3.9"
env: py39-fastapi99
- python: "3.10"
env: py310-fastapi99
- python: "3.11"
env: py311-fastapi99

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python }}
- name: Install dependencies
run: |
pip install --upgrade pip
sh build.sh
pip install tox tox-gh-actions
- name: Run tests using tox
run: tox -e ${{ matrix.env }}
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# caches
.idea
.tox
.pytest_cache
*.egg-info
__pycache__

# docs
docs/node_modules
docs/package-lock.json
docs/.vitepress/cache
docs/.vitepress/dist

# build
build
dist
115 changes: 97 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,107 @@
# fastapi-oauth2
# fastapi-oauth2 <img src="https://github.com/pysnippet.png" align="right" height="64" />

Easy to setup OAuth2 social authentication mechanism with support for several auth providers.
[![PyPI](https://img.shields.io/pypi/v/fastapi-oauth2.svg)](https://pypi.org/project/fastapi-oauth2/)
[![Python](https://img.shields.io/pypi/pyversions/fastapi-oauth2.svg?logoColor=white)](https://pypi.org/project/fastapi-oauth2/)
[![FastAPI](https://img.shields.io/badge/fastapi-%E2%89%A50.68.1-009486)](https://pypi.org/project/fastapi-oauth2/)
[![Tests](https://github.com/pysnippet/fastapi-oauth2/actions/workflows/tests.yml/badge.svg)](https://github.com/pysnippet/fastapi-oauth2/actions/workflows/tests.yml)
[![License](https://img.shields.io/pypi/l/fastapi-oauth2.svg)](https://github.com/pysnippet/fastapi-oauth2/blob/master/LICENSE)

## Demo
FastAPI OAuth2 is a middleware-based social authentication mechanism supporting several auth providers. It depends on
the [social-core](https://github.com/python-social-auth/social-core) authentication backends.

This sample application is made to demonstrate the use of the [**fastapi-oauth2**](./fastapi_oauth2) package.
## Features to be implemented

## Running the application
- Use multiple OAuth2 providers at the same time
* There need to be provided a way to configure the OAuth2 for multiple providers
- Provide `fastapi.security.*` implementations that use cookies
- Token -> user data, user data -> token easy conversion
- Customizable OAuth2 routes
- Registration support

## Installation

```bash
uvicorn main:app --reload
```shell
python -m pip install fastapi-oauth2
```

## TODO
## Configuration

- Make the [**fastapi-oauth2**](./fastapi_oauth2) depend
on (overuse) the [**social-core**](https://github.com/python-social-auth/social-core)
Configuration requires you to provide the JWT requisites and define the clients of the particular providers. The
middleware configuration is declared with the `OAuth2Config` and `OAuth2Client` classes.

## Features
### OAuth2Config

- Integrate with any existing FastAPI project (no dependencies of the project should stop the work of
the `fastapi-oauth2`)
* Implementation must allow to provide a context for configurations (also, see how it is done in another projects)
- Use multiple OAuth2 providers at the same time
* There need to be provided a way to configure the OAuth2 for multiple providers
- Token -> user data, user data -> token easy conversion
- Customize OAuth2 routes
- `allow_http` - Allow insecure HTTP requests. Defaults to `False`.
- `jwt_secret` - The secret key used to sign the JWT. Defaults to `None`.
- `jwt_expires` - The expiration time of the JWT in seconds. Defaults to `900`.
- `jwt_algorithm` - The algorithm used to sign the JWT. Defaults to `HS256`.
- `clients` - The list of the OAuth2 clients. Defaults to `[]`.

### OAuth2Client

- `backend` - The [social-core](https://github.com/python-social-auth/social-core) authentication backend classname.
- `client_id` - The OAuth2 client ID for the particular provider.
- `client_secret` - The OAuth2 client secret for the particular provider.
- `redirect_uri` - The OAuth2 redirect URI to redirect to after success. Defaults to the base URL.
- `scope` - The OAuth2 scope for the particular provider. Defaults to `[]`.

It is also important to mention that for the configured clients of the auth providers, the authorization URLs are
accessible by the `/oauth2/{provider}/auth` path where the `provider` variable represents the exact value of the auth
provider backend `name` attribute.

```python
from fastapi_oauth2.client import OAuth2Client
from fastapi_oauth2.config import OAuth2Config
from social_core.backends.github import GithubOAuth2

oauth2_config = OAuth2Config(
allow_http=False,
jwt_secret=os.getenv("JWT_SECRET"),
jwt_expires=os.getenv("JWT_EXPIRES"),
jwt_algorithm=os.getenv("JWT_ALGORITHM"),
clients=[
OAuth2Client(
backend=GithubOAuth2,
client_id=os.getenv("OAUTH2_CLIENT_ID"),
client_secret=os.getenv("OAUTH2_CLIENT_SECRET"),
redirect_uri="https://pysnippet.org/",
scope=["user:email"],
),
]
)
```

## Integration

To integrate the package into your FastAPI application, you need to add the `OAuth2Middleware` with particular configs
in the above-represented format and include the router to the main router of the application.

```python
from fastapi import FastAPI
from fastapi_oauth2.middleware import OAuth2Middleware
from fastapi_oauth2.router import router as oauth2_router

app = FastAPI()
app.include_router(oauth2_router)
app.add_middleware(OAuth2Middleware, config=oauth2_config)
```

After adding the middleware, the `user` attribute will be available in the request context. It will contain the user
data provided by the OAuth2 provider.

```jinja2
{% if request.user.is_authenticated %}
<a href="/oauth2/logout">Sign out</a>
{% else %}
<a href="/oauth2/github/auth">Sign in</a>
{% endif %}
```

## Contribute

Any contribution is welcome. If you have any ideas or suggestions, feel free to open an issue or a pull request. And
don't forget to add tests for your changes.

## License

Copyright (C) 2023 Artyom Vancyan. [MIT](https://github.com/pysnippet/fastapi-oauth2/blob/master/LICENSE)
39 changes: 0 additions & 39 deletions demo/dependencies.py

This file was deleted.

17 changes: 0 additions & 17 deletions demo/router.py

This file was deleted.

1 change: 0 additions & 1 deletion .env → examples/demonstration/.env
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
OAUTH2_CLIENT_ID=eccd08d6736b7999a32a
OAUTH2_CLIENT_SECRET=642999c1c5f2b3df8b877afdc78252ef5b594d31
OAUTH2_CALLBACK_URL=http://127.0.0.1:8000/oauth2/token

JWT_SECRET=secret
JWT_ALGORITHM=HS256
Expand Down
27 changes: 27 additions & 0 deletions examples/demonstration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## Demonstration

This sample application is made to demonstrate the use of
the [**fastapi-oauth2**](https://github.com/pysnippet/fastapi-oauth2) package.

## Installation

You got to have `fastapi-oauth2` installed in your environment. To do so, run the following command in
the `pyproject.toml` file's directory.

### Regular install

```bash
pip install fastapi-oauth2
```

### Install in editable mode

```bash
pip install -e .
```

## Running the application

```bash
uvicorn main:app --reload
```
25 changes: 25 additions & 0 deletions examples/demonstration/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import os

from dotenv import load_dotenv
from social_core.backends.github import GithubOAuth2

from fastapi_oauth2.client import OAuth2Client
from fastapi_oauth2.config import OAuth2Config

load_dotenv()

oauth2_config = OAuth2Config(
allow_http=True,
jwt_secret=os.getenv("JWT_SECRET"),
jwt_expires=os.getenv("JWT_EXPIRES"),
jwt_algorithm=os.getenv("JWT_ALGORITHM"),
clients=[
OAuth2Client(
backend=GithubOAuth2,
client_id=os.getenv("OAUTH2_CLIENT_ID"),
client_secret=os.getenv("OAUTH2_CLIENT_SECRET"),
# redirect_uri="http://127.0.0.1:8000/",
scope=["user:email"],
),
]
)
14 changes: 14 additions & 0 deletions examples/demonstration/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from fastapi import APIRouter
from fastapi import FastAPI

from config import oauth2_config
from fastapi_oauth2.middleware import OAuth2Middleware
from fastapi_oauth2.router import router as oauth2_router
from router import router as app_router

router = APIRouter()

app = FastAPI()
app.include_router(app_router)
app.include_router(oauth2_router)
app.add_middleware(OAuth2Middleware, config=oauth2_config)
21 changes: 21 additions & 0 deletions examples/demonstration/router.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import json

from fastapi import Depends
from fastapi import Request, APIRouter
from fastapi.responses import HTMLResponse
from fastapi.security import OAuth2
from fastapi.templating import Jinja2Templates

oauth2 = OAuth2()
router = APIRouter()
templates = Jinja2Templates(directory="templates")


@router.get("/", response_class=HTMLResponse)
async def root(request: Request):
return templates.TemplateResponse("index.html", {"request": request, "user": request.user, "json": json})


@router.get("/user")
def user(request: Request, _: str = Depends(oauth2)):
return request.user
Loading