Source code for arxiv.users.legacy.cookies

"""Provides functions for working with legacy session cookies."""

from typing import Tuple
from base64 import b64encode, b64decode
import hashlib
from datetime import datetime, timedelta

from .exceptions import InvalidCookie
from . import util


[docs]def unpack(cookie: str) -> Tuple[str, str, str, datetime, str]: """ Unpack the legacy session cookie. Parameters ---------- cookie : str The value of session cookie. Returns ------- str The session ID associated with the cookie. str The user ID of the authenticated account. str The IP address of the client when the session was created. datetime The datetime when the session was created. datetime The datetime when the session expires. str Legacy user privilege level. Raises ------ :class:`InvalidCookie` Raised if the cookie is detectably malformed or tampered with. """ parts = cookie.split(':') payload: Tuple[str, str, str, datetime, str] if len(parts) < 5: raise InvalidCookie('Malformed cookie') session_id = parts[0] user_id = parts[1] ip = parts[2] issued_at = util.from_epoch(int(parts[3])) expires_at = issued_at + timedelta(seconds=util.get_session_duration()) capabilities = parts[4] try: expected = pack(session_id, user_id, ip, issued_at, capabilities) assert expected == cookie except (TypeError, AssertionError) as e: raise InvalidCookie('Invalid session cookie; forged?') from e return session_id, user_id, ip, issued_at, expires_at, capabilities
[docs]def pack(session_id: str, user_id: str, ip: str, issued_at: datetime, capabilities: str) -> str: """ Generate a value for the classic session cookie. Parameters ---------- session_id : str The session ID associated with the cookie. user_id : str The user ID of the authenticated account. ip : str Client IP address. issued_at : datetime The UNIX time at which the session was initiated. capabilities : str This is essentially a user privilege level. Returns ------- str Signed session cookie value. """ session_hash = util.get_session_hash() value = ':'.join(map(str, [session_id, user_id, ip, util.epoch(issued_at), capabilities])) to_sign = f'{value}-{session_hash}'.encode('utf-8') cookie_hash = b64encode(hashlib.sha1(to_sign).digest()) return value + ':' + cookie_hash.decode('utf-8')[:-1]