fix(chalice): fix refresh token

This commit is contained in:
Taha Yassine Kraiem 2025-03-10 11:25:18 +01:00 committed by Kraiem Taha Yassine
parent 28b580499f
commit afbf5fee7a
4 changed files with 44 additions and 41 deletions

View file

@ -40,8 +40,7 @@ def jwt_authorizer(scheme: str, token: str, leeway=0) -> dict | None:
logger.debug("! JWT Expired signature")
return None
except BaseException as e:
logger.warning("! JWT Base Exception")
logger.debug(e)
logger.warning("! JWT Base Exception", exc_info=e)
return None
return payload
@ -50,10 +49,6 @@ def jwt_refresh_authorizer(scheme: str, token: str):
if scheme.lower() != "bearer":
return None
try:
logger.warning("Checking JWT REF token: %s", token)
logger.warning("Against REF: %s",
config("JWT_REFRESH_SECRET") if not is_spot_token(token) else config("JWT_SPOT_REFRESH_SECRET"))
logger.warning(get_supported_audience())
payload = jwt.decode(jwt=token,
key=config("JWT_REFRESH_SECRET") if not is_spot_token(token) \
else config("JWT_SPOT_REFRESH_SECRET"),
@ -63,8 +58,7 @@ def jwt_refresh_authorizer(scheme: str, token: str):
logger.debug("! JWT-refresh Expired signature")
return None
except BaseException as e:
logger.warning("! JWT-refresh Base Exception")
logger.debug(e)
logger.error("! JWT-refresh Base Exception", exc_info=e)
return None
return payload
@ -83,10 +77,6 @@ def generate_jwt(user_id, tenant_id, iat, aud, for_spot=False):
key=config("JWT_SECRET") if not for_spot else config("JWT_SPOT_SECRET"),
algorithm=config("JWT_ALGORITHM")
)
logger.warning("Generated JWT token: %s", token)
logger.warning("For spot: %s", for_spot)
logger.warning("Using: %s", config("JWT_SECRET") if not for_spot else config("JWT_SPOT_SECRET"))
logger.warning(aud)
return token
@ -105,10 +95,6 @@ def generate_jwt_refresh(user_id, tenant_id, iat, aud, jwt_jti, for_spot=False):
key=config("JWT_REFRESH_SECRET") if not for_spot else config("JWT_SPOT_REFRESH_SECRET"),
algorithm=config("JWT_ALGORITHM")
)
logger.warning("Generated JWT REF token: %s", token)
logger.warning("For spot REF: %s", for_spot)
logger.warning("Using: %s", config("JWT_REFRESH_SECRET") if not for_spot else config("JWT_SPOT_REFRESH_SECRET"))
logger.warning(aud)
return token

View file

@ -3,7 +3,7 @@ import secrets
from decouple import config
from fastapi import BackgroundTasks
from pydantic import BaseModel
from pydantic import BaseModel, model_validator
import schemas
from chalicelib.core import authorizers
@ -284,7 +284,7 @@ def edit_member(user_id_to_update, tenant_id, changes: schemas.EditMemberSchema,
if editor_id != user_id_to_update:
admin = get_user_role(tenant_id=tenant_id, user_id=editor_id)
if not admin["superAdmin"] and not admin["admin"]:
return {"errors": ["unauthorized"]}
return {"errors": ["unauthorized, you must have admin privileges"]}
if admin["admin"] and user["superAdmin"]:
return {"errors": ["only the owner can edit his own details"]}
else:
@ -554,12 +554,21 @@ def refresh_auth_exists(user_id, jwt_jti=None):
class ChangeJwt(BaseModel):
jwt_iat: int
jwt_refresh_jti: int
jwt_refresh_jti: str
jwt_refresh_iat: int
spot_jwt_iat: int
spot_jwt_refresh_jti: int
spot_jwt_refresh_jti: str
spot_jwt_refresh_iat: int
@model_validator(mode="before")
@classmethod
def _transform_data(cls, values):
if values.get("jwt_refresh_jti") is not None:
values["jwt_refresh_jti"] = str(values["jwt_refresh_jti"])
if values.get("jwt_refresh_jti") is not None:
values["spot_jwt_refresh_jti"] = str(values["spot_jwt_refresh_jti"])
return values
def change_jwt_iat_jti(user_id):
with pg_client.PostgresClient() as cur:

View file

@ -7,27 +7,30 @@ from fastapi import HTTPException, status
from starlette.responses import RedirectResponse, FileResponse, JSONResponse, Response
import schemas
from chalicelib.core import scope
from chalicelib.core import assist, signup, feature_flags
from chalicelib.core.metrics import heatmaps
from chalicelib.core.errors import errors, errors_details
from chalicelib.core.sessions import sessions, sessions_notes, sessions_replay, sessions_favorite, sessions_viewed, \
sessions_assignments, unprocessed_sessions, sessions_search
from chalicelib.core import scope
from chalicelib.core import tenants, users, projects, license
from chalicelib.core import webhook
from chalicelib.core.collaborations.collaboration_slack import Slack
from chalicelib.core.errors import errors, errors_details
from chalicelib.core.metrics import heatmaps
from chalicelib.core.sessions import sessions, sessions_notes, sessions_replay, sessions_favorite, sessions_viewed, \
sessions_assignments, unprocessed_sessions, sessions_search
from chalicelib.utils import captcha, smtp
from chalicelib.utils import contextual_validators
from chalicelib.utils import helper
from chalicelib.utils.TimeUTC import TimeUTC
from or_dependencies import OR_context, OR_role
from routers.base import get_routers
from routers.subs import spot
from chalicelib.utils import contextual_validators
logger = logging.getLogger(__name__)
public_app, app, app_apikey = get_routers()
COOKIE_PATH = "/api/refresh"
if config("LOCAL_DEV", cast=bool, default=False):
COOKIE_PATH = "/refresh"
else:
COOKIE_PATH = "/api/refresh"
@public_app.get('/signup', tags=['signup'])
@ -68,18 +71,11 @@ def __process_authentication_response(response: JSONResponse, data: dict) -> dic
max_age=refresh_token_max_age, secure=True, httponly=True)
response.set_cookie(key="spotRefreshToken", value=spot_refresh_token, path=spot.COOKIE_PATH,
max_age=spot_refresh_token_max_age, secure=True, httponly=True)
logger.warning("cookie refreshToken: %s", refresh_token)
logger.warning("cookie spotRefreshToken: %s", spot_refresh_token)
return data
@public_app.post('/login', tags=["authentication"])
def login_user(response: JSONResponse, data: schemas.UserLoginSchema = Body(...)):
# if data.email != 'tahay@asayer.io':
# raise HTTPException(
# status_code=status.HTTP_401_UNAUTHORIZED,
# detail="Enforced testing mode is active."
# )
if helper.allow_captcha() and not captcha.is_valid(data.g_recaptcha_response):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,

View file

@ -4,7 +4,7 @@ import secrets
from decouple import config
from fastapi import BackgroundTasks, HTTPException
from pydantic import BaseModel
from pydantic import BaseModel, model_validator
from starlette import status
import schemas
@ -659,12 +659,21 @@ def refresh_auth_exists(user_id, tenant_id, jwt_jti=None):
class ChangeJwt(BaseModel):
jwt_iat: int
jwt_refresh_jti: int
jwt_refresh_jti: str
jwt_refresh_iat: int
spot_jwt_iat: int
spot_jwt_refresh_jti: int
spot_jwt_refresh_jti: str
spot_jwt_refresh_iat: int
@model_validator(mode="before")
@classmethod
def _transform_data(cls, values):
if values.get("jwt_refresh_jti") is not None:
values["jwt_refresh_jti"] = str(values["jwt_refresh_jti"])
if values.get("jwt_refresh_jti") is not None:
values["spot_jwt_refresh_jti"] = str(values["spot_jwt_refresh_jti"])
return values
def change_jwt_iat_jti(user_id):
with pg_client.PostgresClient() as cur:
@ -759,9 +768,12 @@ def authenticate(email, password, for_change_password=False) -> dict | bool | No
response = {
"jwt": authorizers.generate_jwt(user_id=r['userId'], tenant_id=r['tenantId'], iat=j_r.jwt_iat,
aud=AUDIENCE),
"refreshToken": authorizers.generate_jwt_refresh(user_id=r['userId'], tenant_id=r['tenantId'],
iat=j_r.jwt_refresh_iat, aud=AUDIENCE,
jwt_jti=j_r.jwt_refresh_jti),
"refreshToken": authorizers.generate_jwt_refresh(user_id=r['userId'],
tenant_id=r['tenantId'],
iat=j_r.jwt_refresh_iat,
aud=AUDIENCE,
jwt_jti=j_r.jwt_refresh_jti,
for_spot=False),
"refreshTokenMaxAge": config("JWT_REFRESH_EXPIRATION", cast=int),
"email": email,
"spotJwt": authorizers.generate_jwt(user_id=r['userId'], tenant_id=r['tenantId'],
@ -856,7 +868,7 @@ def logout(user_id: int):
cur.execute(query)
def refresh(user_id: int, tenant_id: int) -> dict:
def refresh(user_id: int, tenant_id: int = -1) -> dict:
jwt_iat, jwt_r_jti, jwt_r_iat = refresh_jwt_iat_jti(user_id=user_id)
return {
"jwt": authorizers.generate_jwt(user_id=user_id, tenant_id=tenant_id, iat=jwt_iat,