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

Implement current_user functionality #19

Closed
signebedi opened this issue Mar 18, 2024 · 4 comments
Closed

Implement current_user functionality #19

signebedi opened this issue Mar 18, 2024 · 4 comments

Comments

@signebedi
Copy link
Owner

signebedi commented Mar 18, 2024

This requires us to wrap the User model in sqlalchemy in pydantic, see here: https://fastapi.tiangolo.com/tutorial/security/get-current-user/ and https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/.

Does it make more sense to make the sql data model ALL into pydantic models, and to use these to construct the database tables instead of hard-coding them in libreforms_fastapi/utils/sqlalchemy_models.py?

This was referenced Mar 20, 2024
@signebedi
Copy link
Owner Author

This has been a huge help: https://www.youtube.com/watch?v=6hTRw_HK3Ts

@signebedi
Copy link
Owner Author

Add token expiry to the json web token used for UI auth
This is still somewhat uncharted territory for me, but I think we should define and implement token expiration based on the PERMANENT_SESSION_LENGTH config.

@signebedi
Copy link
Owner Author

signebedi commented Mar 29, 2024

This might require an authentication backend to make JWT essentially behave like sessions... so, it's a strange patchwork right now. Eventually, we'll need to tighten the auth scheme up.

See here:

In my case, I was using JWT Bearer authentication. So, I also couldn't call request.user where necessary. I did apply the Authentication middleware. Hope this will help.

Writing your own authentication backend

This class is written based on my application structure and needs. You may need this to fit for your application

# Authentication Backend Class
class BearerTokenAuthBackend(AuthenticationBackend):
    """
    This is a custom auth backend class that will allow you to authenticate your request and return auth and user as
    a tuple
    """
    async def authenticate(self, request):
        # This function is inherited from the base class and called by some other class
        if "Authorization" not in request.headers:
            return

        auth = request.headers["Authorization"]
        try:
            scheme, token = auth.split()
            if scheme.lower() != 'bearer':
                return
            decoded = jwt.decode(
                token,
                settings.JWT_SECRET,
                algorithms=[settings.JWT_ALGORITHM],
                options={"verify_aud": False},
            )
        except (ValueError, UnicodeDecodeError, JWTError) as exc:
            raise AuthenticationError('Invalid JWT Token.')

        username: str = decoded.get("sub")
        token_data = TokenData(username=username)
        # This is little hack rather making a generator function for get_db
        db = LocalSession()
        user = User.objects(db).filter(User.id == token_data.username).first()
        # We must close the connection
        db.close()
        if user is None:
            raise AuthenticationError('Invalid JWT Token.')
        return auth, user

Add the middleware on the main file (In my case it's main.py)

@app.on_event('startup')
async def startup():
    app.add_middleware(AuthenticationMiddleware, backend=BearerTokenAuthBackend())

Originally posted by @iashraful in fastapi/fastapi#3043 (comment)

References

  1. AuthenticationMiddleware must be installed to access request.user fastapi/fastapi#3043 (comment)
  2. https://www.starlette.io/authentication

signebedi added a commit that referenced this issue Mar 29, 2024
@signebedi
Copy link
Owner Author

Extend the starlette simple user

Right now, the starlette simple user only stores the username. But, in order to minimize the number of database queries, perhaps we can store a little more - like the user ID and API key...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant