Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
sarus-flask-auth / sarus_flask_auth / timestamp_signer.py
Size: Mime:
""" Copyright (C) Sarus Technologies SAS - All Rights Reserved
Unauthorized copying of this file, via any medium is strictly prohibited
Proprietary and confidential
Write to contact@sarus.tech for more information about purchasing a licence
"""

import datetime
import time
from base64 import urlsafe_b64decode, urlsafe_b64encode

from flask_login.utils import decode_cookie, encode_cookie

"""
Module allowing to sign a message with a flask app's secret key.
The plan was to used it to authenticate messages between the dataowner api
and the private learning lab gateway, as they share a common secret key.

The use of a timestamp offers some degree of protection against attacks where a
previous signed message is replayed by a malicious attacker.

Inspired by:
docs.djangoproject.com/en/3.0/topics/signing/#verifying-timestamped-values
"""


def timestamp():
    t = int(time.time())
    return urlsafe_b64encode(
        t.to_bytes((t.bit_length() + 7) // 8, byteorder="big", signed=False)
    ).decode("ascii")


def decode_timestamp(value):
    return int.from_bytes(
        urlsafe_b64decode(value), byteorder="big", signed=False
    )


def sign(value):
    value = "%s:%s" % (value, timestamp())
    return encode_cookie(value)


def unsign(value, max_age):
    """
    Retrieve original value and check it wasn't signed more
    than max_age seconds ago.
    """
    if isinstance(max_age, datetime.timedelta):
        max_age = max_age.total_seconds()
    result = decode_cookie(value)
    if result is None:
        return
    value, timestamp = result.rsplit(":", 1)
    timestamp = decode_timestamp(timestamp)
    # Check timestamp is not older than max_age
    age = time.time() - timestamp
    if age > max_age:
        return
    return value