aliev / aioauth

Asynchronous OAuth 2.0 provider for Python 3
https://aliev.me/aioauth
MIT License
211 stars 19 forks source link

Questions about the combination of this library and AuthenticationMiddleware #11

Closed hidaris closed 3 years ago

hidaris commented 3 years ago

Description

I tried the example in the readme, but it's not quite clear how to combine it with AuthenticationMiddleware

What I Did

Add some persistent models to the examples in the readme
Gasoid commented 3 years ago

I think it doesn't depend on your OS @hidaris

What error did you get?

Gasoid commented 3 years ago

@aliev how about removing OS from the issue template?

aliev commented 3 years ago

Hi, @hidaris. To access the request.user object fastapi as well as starlette requires the AuthenticationMiddleware.

Here is an example of how you can connect AuthenticationMiddleware to fastapi (JWT example):

from fastapi import FastAPI
from starlette.middleware.authentication import AuthenticationMiddleware
from starlette.authentication import (
    AuthCredentials,
    AuthenticationBackend,
    SimpleUser,
    UnauthenticatedUser,
)

class BasicAuthBackend(AuthenticationBackend):
    async def authenticate(self, request):
        # Get JWT token from user's cookies
        token = request.cookies.get("token")

        # Returns UnauthenticatedUser if token does not exists in cookies
        if not token:
            return AuthCredentials(), UnauthenticatedUser()

        # Checks the validity of the JWT token, if token is invalid returns UnauthenticatedUser object
        try:
            jwt_decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
        except JWTError:
            return AuthCredentials(), UnauthenticatedUser()

        # In case if token is valid returns an object of the authorized user
        return AuthCredentials(["authenticated"]), SimpleUser(jwt_decoded["email"])

...
app = FastAPI()
app.add_middleware(AuthenticationMiddleware, backend=BasicAuthBackend())
...

Now in your views you can check whether the user is authorized or not:

...
user = None
if request.user.is_authenticated:
    user = request.user

return OAuth2Request(
    settings=settings,
    method=RequestMethod[method],
    headers=headers,
    post=Post(**post),
    query=Query(**query_params),
    url=url,
    user=user,
)

I would also recommend the fastapi-users project, which implements the user registration and authentication system for fastapi.

I also want to note that for aioauth.requests.Request the user argument is optional, if the user object is None, aioauth will consider that the user is not authorized.

hidaris commented 3 years ago

Thanks for the detailed explanation!