FastAPI auth with jwt, but not OAuth2 - is it possible to customize built-in OAuth2PasswordBearer?

Viewed 755

On my frontend there is some custom auth flow with jwt, which differs from OAuth2 flow (clearly described in FastAPI docs), only by how credentials are sent to /login endpoint. Frontend makes POST with json in body {"email": "...", "password": "..."} instead of username; password in form data.

Is there some way to customize OAuth2PasswordBearer or some other built-in security class to support this scenario? It will be nice to still have fully-functional SwaggerUI docs with Authorize form etc.

I see there are many recipes, how to support jwt, but most of them are not integrated well with SwaggerUI docs and it will be nice to base solution on some class buit-into FastAPI itself.

1 Answers

If I have understood you well, the only thing you want to change is what is passed to your login endpoint.

In the docs of FastAPI, they show the usage of a class named OAuth2PasswordRequestForm. This class is responsible for how that input data is passed. You can create another class that will be treated as a model and therefore will be passed as JSON in the body of the request.

Just like this:

class OAuth2PasswordRequestJSON(BaseModel):
    grant_type: str = Field(None, regex="password")
    username: str = Field(...)
    password: str = Field(...)
    scope: List[str] = Field(default_factory=list)
    client_id: Optional[str] = None
    client_secret: Optional[str] = None

    @validator("scope", pre=True)
    def scope_from_string(cls, v):
        return v.split() if isinstance(v, str) else v


@app.post("/token")
async def login(body_data: OAuth2PasswordRequestJSON):
    ...

Hopefully, this is what you meant.

Edit 1:

As Anton mentioned, the Swagger UI will not support this new endpoint. Looking at the following issue in its repository, it seems that there will be no support for application/json Content-Type in the UI.

Anyway, if you want to support this flow in your system, you can serve an edited copy of swagger-ui-bundle.js which could send the data as you wish.

The edits that should be done are:

  • Remove buildFormData from line 114 in actions.js. From:

    authActions.authorizeRequest({ body: buildFormData(form), url: schema.get("tokenUrl"), name, headers, query, auth})
    

    To:

    authActions.authorizeRequest({ body: form, url: schema.get("tokenUrl"), name, headers, query, auth})
    
  • Change the Content-Type to be application/json at line 192 in actions.js From:

    "Content-Type": "application/x-www-form-urlencoded",
    

    To:

    "Content-Type": "application/json",
    

To serve your file, follow the docs in Self-hosting javascript in FastAPI.

Good Luck :)

Related