File size: 1,739 Bytes
72b125b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
"""Bearer-token auth for the mobile app (Flask sessions are unreliable on native clients)."""
from flask import current_app, request, session
from itsdangerous import BadSignature, SignatureExpired, URLSafeTimedSerializer

TOKEN_SALT = "anicove-mobile-auth"
TOKEN_MAX_AGE = 30 * 24 * 60 * 60


def _serializer():
    return URLSafeTimedSerializer(current_app.config["SECRET_KEY"], salt=TOKEN_SALT)


def issue_mobile_token(user_id, username, avatar=None):
    return _serializer().dumps({
        "user_id": str(user_id),
        "username": username,
        "avatar": avatar,
    })


def parse_mobile_token(token):
    try:
        return _serializer().loads(token, max_age=TOKEN_MAX_AGE)
    except (BadSignature, SignatureExpired, TypeError, ValueError):
        return None


def require_mobile_auth():
    """Return (user_id, username, avatar) from session or Bearer token."""
    if session.get("username") and session.get("_id") is not None:
        return str(session["_id"]), session["username"], session.get("avatar")

    header = request.headers.get("Authorization") or ""
    token = ""
    if header.lower().startswith("bearer "):
        token = header.split(" ", 1)[1].strip()
    if not token:
        token = (request.headers.get("X-Auth-Token") or "").strip()
    if not token:
        data = request.get_json(silent=True) or {}
        token = str(data.get("token") or request.args.get("token") or "").strip()
    if not token:
        return None

    payload = parse_mobile_token(token)
    if not payload or not payload.get("user_id") or not payload.get("username"):
        return None
    return str(payload["user_id"]), payload["username"], payload.get("avatar")