Token refresh #350
Replies: 20 comments 17 replies
-
The purpose of this refresh endpoint is to get a new token while you still have a valid one. A common use-case is to call it whenever your user gets back into your app. This way, you ensure you always have a fresh one before the previous expires. You should call it with a JWT or Cookie (depending on what you use) ; like any other protected endpoint. |
Beta Was this translation helpful? Give feedback.
-
thank you!! |
Beta Was this translation helpful? Give feedback.
-
From what I see, you recommend to use existing token to refresh it. What if it leaks? The attacker could refresh it indefinitely and due to nature of JWT tokens, you'd be left with no option to revoke it. I think it poses a security threat. |
Beta Was this translation helpful? Give feedback.
-
This is exactly why it's not implemented by default in the library. Each developer has the liberty to implement it better. |
Beta Was this translation helpful? Give feedback.
-
I see. Well, thanks for clarifying that! |
Beta Was this translation helpful? Give feedback.
-
I think a big draw to fastapi-users is how much it does for you. DB setup, routes, forgot-password, (verify email soon 🤞). I think refresh token is a requirement for most projects once they get off the ground, and it seems like a perfect fit to add to this library. For my part, I'm actually going to switch off fastapi-users to fastapi-jwt-auth since it handles refresh tokens. I've wrestled some with how to use fastapi-users for 90%, and defer to fastapi-jwt-auth just for refresh tokens; but it seems it might turn into a Frankenstein, based on how they each handle jwt verification dependency-injection. Instead, I might flip it; use fastapi-jwt-auth as the core, and see about using fastapi-users just for forgot-password & other bits. All that's to say: we definitely don't want to doubt your decision to defer refresh-tokens to the developer, you're close to the metal and know what's best. But you might find it's a deal-breaker for a lot of people (is for me), who don't know enough jwt/security to tackle this themselves, deferring instead to the experts (yourself). Unless there's some clear path to implementing proper refresh-token flow via fastapi-users on the developers' side that we're not seeing? |
Beta Was this translation helpful? Give feedback.
-
Hey @lefnire! Thank your for the detailed feedback! I totally get your point, and I think you convinced me 😅 I've checked Now, as you surely know, open-source is hard and time-consuming. I would like to have more time to work on But I promise you that I'll revisit this (and also email verification 😉) when I get time. I see two ways of implementing this:
I reopen this issue and mark it as enhancement. Thanks ;) |
Beta Was this translation helpful? Give feedback.
-
That's wonderful news! Thanks for hearing us out.
No doubt, and thanks for all your work thus far. We were just concerned it was being marked "out of scope" rather than "help wanted / someday". Hopefully one of us can help! |
Beta Was this translation helpful? Give feedback.
-
I think that (option 2) is a great idea personally, let them handle some of the guts and fastapi-users can be more the layer on top. Saves dev work, since contribs here can fix bugs there, instead of two places. Actually wonder if / how much of fastapi-users could be refactored to use fastapi-jwt-auth under the hood for current tasks, then you could focus more on the developer-facing features. One trick worth consideration before work begins. Common practice that refresh tokens use |
Beta Was this translation helpful? Give feedback.
-
ocdevel/gnothi#124 if anyone wants to see how to blend fastapi-users + fastapi-jwt-auth to get refresh tokens |
Beta Was this translation helpful? Give feedback.
-
The |
Beta Was this translation helpful? Give feedback.
-
Simple and effective way to add https://frankie567.github.io/fastapi-users/configuration/authentication/jwt/#tip-refresh |
Beta Was this translation helpful? Give feedback.
-
Hey @frankie567,
do you already have a rough estimate on the time point you want to re-visit this? No pressure, or haste or anything like this - the info would just be helpful to me (and possibly others) to see if and for how long I will need to find a work-around for this (: Thanks for the great library! |
Beta Was this translation helpful? Give feedback.
-
@frankie567 - if it's OK, I'd like to have a go at this given this is something I'll be implementing anyway for my project. My suggestion is not to use fastapi-jwt-auth directly because it seems no longer to be maintained (the last commit was 17 months ago) but to create a similar implementation of the freshness token pattern. Would a PR in this direction be welcome? |
Beta Was this translation helpful? Give feedback.
-
What are the implications of something like this until an official method is available?
|
Beta Was this translation helpful? Give feedback.
-
All your comments are incredibly useful. @frankie567 What I do is I save the refresh token to any caching server such as Redis and read an @app.get("/auth/jwt/refresh")
async def refresh_jwt(strategy: Annotated[JWTStrategy, Depends(get_jwt_strategy)], refresh_token: Annotated[str, Cookie()], user=Depends(current_user)):
valid_token = check_refresh_token(refresh_token)
if not valid_token:
raise HTTPException(status_code=401, detail='Invalid token')
token = await strategy.write_token(user)
return await bearer_transport.get_login_response(token) You can add your own logic in def check_refresh_token(token: str) -> bool:
# Check expiry in Redis instead of in cookie
# If expired then return False
# Sample
return True Is this a good implementation? |
Beta Was this translation helpful? Give feedback.
-
As mentioned in my reply to enchance above (#350 (reply in thread)) I have been trying to adjust/extend the initial login response to include an initial refresh token in addition to the already provided access token. Just wanted to share/discuss my solution to help others/find potential pitfalls in this solution. Maybe it is also something that could be implemented in the next version of fastapi-users in a better/easier manner than my current workaround. @frankie567, I believe that by providing the extra BearerTransportRefresh and extending the Authentication Backend (potentially as an optional argument), we could make it easy to implement the provision of an initial refresh token. What's not yet considered in this approach is potentially storing the initial refresh token in redis etc to implement token rotation. I am not sure what the current status on the topic is in general and if this is something you'd like to see in the package, especially considering all the work that @jtv8 put in his PR regarding the topic already. Either way, if this is of interest or you'd like some help otherwise, I'd be happy to do a PR or contribute. This has been my current attempt:
This has led me to extend the AuthenticationBackend (in order to use the extended BearerTransportRefresh)
and obtaining the extended auth backend
|
Beta Was this translation helpful? Give feedback.
-
Hello everyone, any news about this? |
Beta Was this translation helpful? Give feedback.
-
Hello Folks, excited to read the conversation. Do we have a solution yet? |
Beta Was this translation helpful? Give feedback.
-
I've been searching for solution. And found PRs with a lot of changes. In my opinion, it is a little bit dangerous in production to write core logic based on unmerged PRs, so here i want to show my solution (It is a little bit dirty, but it works)
Here i redefined get_auth_router function that provides router with /login and /logout endpoints. I added creating and storing refresh token into refresh_strategy (in my project i use RedisStrategy). /core/auth.py
Just created Redis refresh strategy with key prefix for storing refresh_keys /routers/..../user.py
Here is my definition of /refresh endpoint, where you try to get refresh_token from cookies and renew it, also give new access & refresh to user. Also, there is a leak that i dont try invalidate access token, however it lives for 10 minutes in my case and i see flow as Request -> 401 token expired -> /refresh -> new access. If someone has ideas how to improve this code, you are welcome! |
Beta Was this translation helpful? Give feedback.
-
I have many doubts about token refresh implementation in the docs:
How can I use this function on a real project?...
About "get_current_active_user" -> Will throw a 401 Unauthorized if missing or wrong credentials... by time I call this function the token already expired so the user is Unauthorized ...how could this work ?
What should I send in response param ?
Beta Was this translation helpful? Give feedback.
All reactions