api auth
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
from typing import Optional
|
||||
|
||||
from flask import current_app
|
||||
from itsdangerous import BadSignature, SignatureExpired, URLSafeTimedSerializer
|
||||
|
||||
from .extensions import db
|
||||
from .models import User
|
||||
|
||||
TOKEN_SALT = "fueltrack-api-access-token-v1"
|
||||
|
||||
|
||||
def _serializer() -> URLSafeTimedSerializer:
|
||||
return URLSafeTimedSerializer(current_app.config["SECRET_KEY"], salt=TOKEN_SALT)
|
||||
|
||||
|
||||
def _password_stamp(user: User) -> str:
|
||||
"""Unieważnia token po zmianie hasła bez przechowywania tokenów w bazie."""
|
||||
return hashlib.sha256(user.password_hash.encode("utf-8")).hexdigest()[:16]
|
||||
|
||||
|
||||
def create_access_token(user: User) -> str:
|
||||
return _serializer().dumps({"uid": user.id, "pwd": _password_stamp(user)})
|
||||
|
||||
|
||||
def load_access_token(token: str) -> Optional[User]:
|
||||
try:
|
||||
payload = _serializer().loads(
|
||||
token,
|
||||
max_age=int(current_app.config["API_TOKEN_MAX_AGE_SECONDS"]),
|
||||
)
|
||||
user = db.session.get(User, int(payload["uid"]))
|
||||
except (BadSignature, SignatureExpired, KeyError, TypeError, ValueError):
|
||||
return None
|
||||
|
||||
if not user or not user.active:
|
||||
return None
|
||||
if payload.get("pwd") != _password_stamp(user):
|
||||
return None
|
||||
return user
|
||||
Reference in New Issue
Block a user