fix refresh token

This commit is contained in:
2025-12-28 11:55:30 +05:00
parent 2322b27ace
commit 5db5b98dbc
2 changed files with 68 additions and 15 deletions

View File

@ -128,6 +128,10 @@ class AuthService:
access_token = create_access_token({"sub": user["username"], "uuid": user["uuid"]}) access_token = create_access_token({"sub": user["username"], "uuid": user["uuid"]})
client_token = str(uuid.uuid4()) client_token = str(uuid.uuid4())
await sessions_collection.delete_many({
"user_uuid": user["uuid"]
})
# Сохраняем сессию # Сохраняем сессию
session = Session( session = Session(
access_token=access_token, access_token=access_token,
@ -147,14 +151,19 @@ class AuthService:
} }
async def validate(self, access_token: str, client_token: str): async def validate(self, access_token: str, client_token: str):
print(f"Searching for access_toke and client_token: '{access_token}', '{client_token}")
session = await sessions_collection.find_one({ session = await sessions_collection.find_one({
"access_token": access_token, "access_token": access_token,
"client_token": client_token, "client_token": client_token,
}) })
print("Session from DB:", session)
if not session or datetime.utcnow() > session["expires_at"]: if not session:
return False return False
if datetime.utcnow() > session["expires_at"]:
# можно сразу чистить
await sessions_collection.delete_one({"_id": session["_id"]})
return False
return True return True
async def is_admin(self, access_token: str, client_token: str) -> bool: async def is_admin(self, access_token: str, client_token: str) -> bool:
@ -187,16 +196,46 @@ class AuthService:
} }
async def refresh(self, access_token: str, client_token: str): async def refresh(self, access_token: str, client_token: str):
if not await self.validate(access_token, client_token): session = await sessions_collection.find_one({
"access_token": access_token,
"client_token": client_token,
})
if not session:
return None return None
# Обновляем токен if datetime.utcnow() > session["expires_at"]:
new_access_token = create_access_token({"sub": "user", "uuid": "user_uuid"}) return None
user = await users_collection.find_one({"uuid": session["user_uuid"]})
if not user:
return None
new_access_token = create_access_token({
"sub": user["username"],
"uuid": user["uuid"],
})
new_expires_at = datetime.utcnow() + timedelta(minutes=1440)
await sessions_collection.update_one( await sessions_collection.update_one(
{"access_token": access_token}, {"_id": session["_id"]},
{"$set": {"access_token": new_access_token}}, {
"$set": {
"access_token": new_access_token,
"expires_at": new_expires_at,
}
},
) )
return {"accessToken": new_access_token, "clientToken": client_token}
return {
"accessToken": new_access_token,
"clientToken": client_token,
"selectedProfile": {
"id": user["uuid"],
"name": user["username"],
},
}
async def get_minecraft_profile(self, uuid: str): async def get_minecraft_profile(self, uuid: str):
# Преобразуем UUID без дефисов в формат с дефисами (если нужно) # Преобразуем UUID без дефисов в формат с дефисами (если нужно)
@ -291,12 +330,20 @@ class AuthService:
async def join_server(self, request_data: dict): async def join_server(self, request_data: dict):
access_token = request_data.get("accessToken") access_token = request_data.get("accessToken")
selected_profile = request_data.get("selectedProfile") # UUID без дефисов selected_profile = request_data.get("selectedProfile")
server_id = request_data.get("serverId") server_id = request_data.get("serverId")
if not all([access_token, selected_profile, server_id]): if not all([access_token, selected_profile, server_id]):
raise HTTPException(status_code=400, detail="Missing required parameters") raise HTTPException(status_code=400, detail="Missing required parameters")
session = await sessions_collection.find_one({
"access_token": access_token,
"client_token": request_data.get("clientToken"),
})
if not session or datetime.utcnow() > session["expires_at"]:
raise HTTPException(status_code=401, detail="Invalid or expired session")
decoded_token = decode_token(access_token) decoded_token = decode_token(access_token)
if not decoded_token: if not decoded_token:
raise HTTPException(status_code=401, detail="Invalid access token") raise HTTPException(status_code=401, detail="Invalid access token")
@ -305,11 +352,9 @@ class AuthService:
if token_uuid != selected_profile: if token_uuid != selected_profile:
raise HTTPException(status_code=403, detail="Token doesn't match selected profile") raise HTTPException(status_code=403, detail="Token doesn't match selected profile")
# Сохраняем server_id в сессию
await sessions_collection.update_one( await sessions_collection.update_one(
{"user_uuid": decoded_token["uuid"]}, # UUID с дефисами {"_id": session["_id"]},
{"$set": {"server_id": server_id}}, {"$set": {"server_id": server_id}},
upsert=True
) )
return True return True
@ -321,8 +366,9 @@ class AuthService:
# Ищем сессию с этим server_id # Ищем сессию с этим server_id
session = await sessions_collection.find_one({ session = await sessions_collection.find_one({
"user_uuid": user["uuid"], # UUID с дефисами "user_uuid": user["uuid"],
"server_id": server_id "server_id": server_id,
"expires_at": {"$gt": datetime.utcnow()},
}) })
if not session: if not session:
raise HTTPException(status_code=403, detail="Not joined this server") raise HTTPException(status_code=403, detail="Not joined this server")

View File

@ -11,6 +11,7 @@ from app.services.promo import PromoService
from app.webhooks import telegram from app.webhooks import telegram
from app.db.database import users_collection from app.db.database import users_collection
from app.api import marketplace_ws from app.api import marketplace_ws
from app.db.database import users_collection, sessions_collection
###################### БОТ ###################### ###################### БОТ ######################
@ -23,6 +24,12 @@ WEBHOOK_SECRET = os.getenv("TELEGRAM_WEBHOOK_SECRET", "")
async def lifespan(app: FastAPI): async def lifespan(app: FastAPI):
# ===== STARTUP ===== # ===== STARTUP =====
# TTL для сессий (автоочистка)
await sessions_collection.create_index(
"expires_at",
expireAfterSeconds=0
)
await users_collection.create_index("expires_at", expireAfterSeconds=0) await users_collection.create_index("expires_at", expireAfterSeconds=0)
await users_collection.create_index("telegram_user_id", unique=True, sparse=True) await users_collection.create_index("telegram_user_id", unique=True, sparse=True)