fastapi icon indicating copy to clipboard operation
fastapi copied to clipboard

First-class session support in FastAPI

Open sm-Fifteen opened this issue 4 years ago • 33 comments

Is your feature request related to a problem

All of the security schemas currently supported by FastAPI rely on some sort of "client-server synergy" , where, for instance, the client is expected to know and remember an OAuth token or the user credentials to be sent via headers. This works fairly well for single-page applications, but if you need to integrate authentication to an app that uses templates, keeping track of that authentication data becomes a challenge. Most applications would use server-side sessions to deal with this, but FastAPI doesn't really have a system to deal with sessions right now.

Describe alternatives you've considered

Using Starlette's SessionMiddleware

While Starlette's SessionMiddleware is mentionned a number of times in the FastAPI documentation, it does not integrate very well with the framework itself . What it does is that it adds a request.session dict on the Request object that lets the backend store and retreive information from it, and just before the response get sent, that dict is serialized, combined to a timestamp, signed, converted into base 64 and appended as a cookie. The client is then expected to send theat cookie back so that the server so that information can be decoded and used. This is what the Django doc describes as the cookie-based approach.

The problem with all this is that the entire process happens outside of what FastAPI can handle, and therefore does not appear in the generated OpenAPI documentation as an authentication schema.

Having read the source for that middleware and the documentation for itsdangerous, I also understand that this kind of "session blob" authentication method isn't really supported by OpenAPI, since all supported auth methods are expected to use constants to handle authentication.

The solution you would like

Ideally, I would like to see FastAPI adding some kind of SessionCookie[T] class to fastapi.security, that would register a cookie-based API key authentication method (which is what Swagger reccomands, since sessions are out of scope for the OpenAPI spec). Those "API keys" would be session tokens, much like the It should also register that routes that depend on that security schema may reply with a Set-Cookie header.

The question of how that data would be persisted afterwards is an open one. Having a one-size-fits-all implementation as the only one available could be constraining, so there's always the option of a fastapi.security.sessions namespace containing things like MemorySessionStorage, DatabaseSessionStorage, FileSessionStorage and so on.

Additional context

Maybe something like this?

from fastapi import Depends, FastAPI
from fastapi.security.sessions import SessionCookie, MemorySessionStorage
from pydantic import BaseModel
from datetime import timedelta

app = FastAPI()

class SessData(BaseModel):
    # BaseModel so it can be serialized and stored properly
    uname: str

security = SessionCookie[SessData](
    name='fastapi_sess',
    expires=timedelta(hours=1).
    backend=MemorySessionStorage(),
    auto_error=False
)

@app.get('/secure/rm_rf/{path:path}')
def secure_thing(path: str, session: Optional[SessData] = Depends(security)):
    if session is not None and session.uname == 'root':
        # ...

sm-Fifteen avatar Nov 29 '19 17:11 sm-Fifteen