Skip to content

Improve extensibility of Transport and Strategy #1493

@ldub

Description

@ldub

I want to use FastAPI as a backend for an app that has sign in with google and no other sign in options. I also want to use jwt authentication for each request. Using OAuth2PasswordBearer doesn't work for me - the OpenAPI spec is then generated with a whole user/password flow and requires hitting an endpoint.

The authorize button in swagger shows this whole thing, that I don't need, or want.

Image

I just want to provide a Bearer token and be able to use that for authenticated requests. fastapi-users does let us customize. Lets use fastapi.security.HTTPBearer as the scheme, and build a simple custom transport

# skipping most imports
from fastapi.security import HTTPBearer

class HTTPBearerTransport(Transport):
    scheme: HTTPBearer

    def __init__(self):
        self.scheme = HTTPBearer()

   # most everything else the same as OAuth2PasswordBearer

However, this customizability doesn't actually work very well with fastapi-users handling of JWTs.

The scheme/transport returns a HTTPAuthorizationCredentials from fastapi.

But the JWTStrategy in fastapi-users requires a str. There is no way to tell fastapi-users that you need to pull the .credentials property out of the object returned by the transport.

You then need to write a custom JWTStrategy

class HTTPAuthorizationCredentialsJWTStrategy(JWTStrategy):
    async def read_token(
        self, token: HTTPAuthorizationCredentials | None, user_manager: UserManager
    ):
        token_str = None
        if token is not None:
            token_str = token.credentials
        return await super().read_token(token_str, user_manager)


def get_jwt_strategy() -> JWTStrategy:
    return HTTPAuthorizationCredentialsJWTStrategy(
        secret=settings.JWT_SECRET,
        lifetime_seconds=3600,
        token_audience=["fastapi-users:auth"],
    )

All of this actually does work - but it is super unergonomic and it means that the extensibility of using a custom transport and strategy is relatively unstable. I was wondering if you might be open to improving the API here such that either the transport or the jwt strategy allows the client to pass in a way to get the underlying token?

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions