MushroomMaula / fastapi_login

FastAPI-Login tries to provide similar functionality as Flask-Login does.
https://pypi.org/project/fastapi-login
MIT License
639 stars 58 forks source link

refresh token function #45

Closed kigawas closed 8 months ago

kigawas commented 3 years ago

My current solution is:

ACCESS_TOKEN_SCOPE = "access"
REFRESH_TOKEN_SCOPE = "refresh"

def create_access_token(manager: LoginManager, data: dict):
    # data.update({"_type": ACCESS_TOKEN_SCOPE})
    return manager.create_access_token(
        data=data,
        expires=timedelta(minutes=120),
        scopes=[ACCESS_TOKEN_SCOPE],
    )

def create_refresh_token(manager: LoginManager, data: dict):
    # data.update({"_type": REFRESH_TOKEN_SCOPE})
    return manager.create_access_token(
        data=data,
        expires=timedelta(days=15),
        scopes=[REFRESH_TOKEN_SCOPE],
    )

It'll be better to add some handy functions to get refresh token :)

MushroomMaula commented 3 years ago

I don't think it's necessary to add this as a own function the LoginManager class. IMO refresh tokens should be accessible on it's own url path (e.g. /auth/refresh), if a new refresh token function would be added, it would not show up as a authentication route in the API docs if I'm not mistaken. Furthermore I think the implementation of refresh tokens is project dependant and the expiry time etc. may differ from project to project. So we would probably end up with a function with the same siganture as LoginManager.create_access_token

gurbaaz27 commented 2 years ago

@kigawas with this approach, does simply using Depends(manager) in api routes work, or you need to use Security(manager, scopes=[required scopes here]) for each of the api? What is the exact thing you have to follow for other apis, and for /refresh api (I assume that would be different)?

kigawas commented 2 years ago

@gurbaaz27

You need Security:

get_payload_by_access = Security(LOGIN_MANAGER, scopes=[ACCESS_TOKEN_SCOPE])
get_payload_by_refresh = Security(LOGIN_MANAGER, scopes=[REFRESH_TOKEN_SCOPE])

And in your API, for example:

from .depends import get_payload_by_access, get_payload_by_refresh

@router.post("/refresh")
async def _(
    payload: dict = get_payload_by_refresh,
):
    return create_access_token(manager, payload)

@router.delete("/logout")
async def _(
    redis: Redis = Depends(get_redis),
    payload: dict = get_payload_by_access,
):
    await delete_session(redis, payload["user_id"])
gurbaaz27 commented 2 years ago

@kigawas Thanks man, appreciate the quick response!