35 lines
970 B
Python
35 lines
970 B
Python
|
|
"""JWT encode/decode helpers."""
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from datetime import UTC, datetime, timedelta
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
import jwt
|
||
|
|
from flask import current_app
|
||
|
|
|
||
|
|
|
||
|
|
def encode_token(user_id: int, role: str) -> str:
|
||
|
|
"""Return a signed JWT for the given user."""
|
||
|
|
now = datetime.now(UTC)
|
||
|
|
exp_minutes = current_app.config["JWT_EXP_MINUTES"]
|
||
|
|
payload: dict[str, Any] = {
|
||
|
|
"sub": str(user_id),
|
||
|
|
"role": role,
|
||
|
|
"iat": int(now.timestamp()),
|
||
|
|
"exp": int((now + timedelta(minutes=exp_minutes)).timestamp()),
|
||
|
|
}
|
||
|
|
return jwt.encode(
|
||
|
|
payload,
|
||
|
|
current_app.config["JWT_SECRET"],
|
||
|
|
algorithm=current_app.config["JWT_ALGORITHM"],
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def decode_token(token: str) -> dict[str, Any]:
|
||
|
|
"""Decode + validate a JWT. Raises jwt.PyJWTError on failure."""
|
||
|
|
return jwt.decode(
|
||
|
|
token,
|
||
|
|
current_app.config["JWT_SECRET"],
|
||
|
|
algorithms=[current_app.config["JWT_ALGORITHM"]],
|
||
|
|
)
|