-
Notifications
You must be signed in to change notification settings - Fork 143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
After modifying the password, need to disable the token of other clients. #14
Comments
Hello, @dongfengweixiao yes this is a really important feature. I am going to add it. |
Hello, @jonra1993 The above code may help you. |
Hi @dongfengweixiao this feature has been implemented in this commit c7c38d5 Please check it. |
The password change function is available, but there is a problem: the old refresh token is still valid. |
diff --git a/fastapi-alembic-sqlmodel-async/app/api/v1/endpoints/login.py b/fastapi-alembic-sqlmodel-async/app/api/v1/endpoints/login.py
index 0d929c1..50491aa 100644
--- a/fastapi-alembic-sqlmodel-async/app/api/v1/endpoints/login.py
+++ b/fastapi-alembic-sqlmodel-async/app/api/v1/endpoints/login.py
@@ -1,5 +1,5 @@
from datetime import timedelta
-from typing import Any
+from typing import Any, Optional
from fastapi import APIRouter, Body, Depends, HTTPException
from app.core.security import get_password_hash
from app.core.security import verify_password
@@ -27,12 +27,13 @@ class TokenType(str, Enum):
async def add_token_to_redis(
- redis_client: Redis, user: User, token: str, token_type: TokenType, expire_time: int
+ redis_client: Redis, user: User, token: str, token_type: TokenType, expire_time: Optional[int] = None
):
token_key = f"user:{user.id}:{token_type}"
print("token_key", token_key)
await redis_client.sadd(token_key, token)
- await redis_client.expire(token_key, expire_time)
+ if expire_time:
+ await redis_client.expire(token_key, expire_time)
print("done")
@@ -70,20 +71,24 @@ async def login(
refresh_token=refresh_token,
user=user,
)
- await add_token_to_redis(
- redis_client,
- user,
- access_token,
- TokenType.ACCESS,
- settings.ACCESS_TOKEN_EXPIRE_MINUTES,
- )
- await add_token_to_redis(
- redis_client,
- user,
- refresh_token,
- TokenType.REFRESH,
- settings.REFRESH_TOKEN_EXPIRE_MINUTES,
- )
+ access_token_key = f"user:{user.id}:{TokenType.ACCESS}"
+ valid_access_tokens = await redis_client.smembers(access_token_key)
+ if valid_access_tokens:
+ await add_token_to_redis(
+ redis_client,
+ user,
+ access_token,
+ TokenType.ACCESS,
+ )
+ refresh_token_key = f"user:{user.id}:{TokenType.REFRESH}"
+ valid_refresh_tokens = await redis_client.smembers(refresh_token_key)
+ if valid_refresh_tokens:
+ await add_token_to_redis(
+ redis_client,
+ user,
+ refresh_token,
+ TokenType.REFRESH,
+ )
return create_response(meta=meta_data, data=data, message="Login correctly")
@@ -159,6 +164,12 @@ async def get_refresh_token(
except (jwt.JWTError, ValidationError):
raise HTTPException(status_code=403, detail="Refresh token invalid")
+ user_id = payload["sub"]
+ refresh_token_key = f"user:{user_id}:{TokenType.REFRESH}"
+ valid_refresh_tokens = await redis_client.smembers(refresh_token_key)
+ if valid_refresh_tokens and body.refresh_token not in valid_refresh_tokens:
+ raise HTTPException(status_code=403, detail="Refresh token invalid")
+
if payload["type"] == "refresh":
access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
user = await crud.user.get(id=payload["sub"])
|
Sure you are right @dongfengweixiao this commit validates refresh token 33862a1 2c9ac33 |
Fantastic job. |
It is unnecessary to record the token in Redis for normal login action. When the password is changed, the new token will be record to Redis. There are two cases when other clients log in. Case 1: There are records in Redis. At this time, when other clients log in, they need to check whether there is a token in Redis. If yes, they need to put token to Redis together. |
Hello @dongfengweixiao I caught your logic now. Please check this commit b9ff90c and let me know what do you think |
logic is right, but in login function, you call redis three times: read token from redis(get_valid_tokens) -> read token from redis again(add_token_to_redis) -> write token to redis. |
The text was updated successfully, but these errors were encountered: