diff --git a/README.rst b/README.rst index 62d2b15..750fef6 100644 --- a/README.rst +++ b/README.rst @@ -186,6 +186,9 @@ PyBankID can generate QR codes for you, and there is an example application in t `examples folder of the repo `_ where a Flask application called ``qrdemo`` shows one way to do authentication with animated QR codes. +The QR code content generation is done with the ``generate_qr_code_content`` method on the BankID Client instances, or diectly +through the identically named method in ``bankid.qr`` module. + Certificates ------------ @@ -226,4 +229,5 @@ The PyBankID solution can be tested with `pytest `_: .. code-block:: bash - py.test tests/ +pytest tests/ + diff --git a/bankid/__init__.py b/bankid/__init__.py index 7f628bc..044ba3e 100644 --- a/bankid/__init__.py +++ b/bankid/__init__.py @@ -23,12 +23,14 @@ from bankid.certutils import create_bankid_test_server_cert_and_key from bankid.syncclient import BankIDClient from bankid.asyncclient import BankIDAsyncClient +from bankid.qr import generate_qr_code_content __all__ = [ "BankIDClient", "BankIDAsyncClient", "exceptions", "create_bankid_test_server_cert_and_key", + "generate_qr_code_content", "__version__", "version", ] diff --git a/bankid/baseclient.py b/bankid/baseclient.py index 0d146f6..95c9103 100644 --- a/bankid/baseclient.py +++ b/bankid/baseclient.py @@ -1,12 +1,9 @@ import base64 from datetime import datetime -import hashlib -import hmac -from math import floor -import time from typing import Tuple, Optional, Dict, Any from urllib.parse import urljoin +from bankid.qr import generate_qr_code_content from bankid.certutils import resolve_cert_path @@ -42,19 +39,8 @@ def __init__( self.client = None @staticmethod - def generate_qr_code_content(qr_start_token: str, start_t: [float, datetime], qr_start_secret: str): - """Given QR start token, time.time() or UTC datetime when initiated authentication call was made and the - QR start secret, calculate the current QR code content to display. - """ - if isinstance(start_t, datetime): - start_t = start_t.timestamp() - elapsed_seconds_since_call = int(floor(time.time() - start_t)) - qr_auth_code = hmac.new( - qr_start_secret.encode(), - msg=str(elapsed_seconds_since_call).encode(), - digestmod=hashlib.sha256, - ).hexdigest() - return f"bankid.{qr_start_token}.{elapsed_seconds_since_call}.{qr_auth_code}" + def generate_qr_code_content(qr_start_token: str, start_t: [float, datetime], qr_start_secret: str) -> str: + return generate_qr_code_content(qr_start_token, start_t, qr_start_secret) @staticmethod def _encode_user_data(user_data): diff --git a/bankid/qr.py b/bankid/qr.py new file mode 100644 index 0000000..d1e375c --- /dev/null +++ b/bankid/qr.py @@ -0,0 +1,20 @@ +import hashlib +import hmac +import time +from datetime import datetime +from math import floor + + +def generate_qr_code_content(qr_start_token: str, start_t: [float, datetime], qr_start_secret: str) -> str: + """Given QR start token, time.time() or UTC datetime when initiated authentication call was made and the + QR start secret, calculate the current QR code content to display. + """ + if isinstance(start_t, datetime): + start_t = start_t.timestamp() + elapsed_seconds_since_call = int(floor(time.time() - start_t)) + qr_auth_code = hmac.new( + qr_start_secret.encode(), + msg=str(elapsed_seconds_since_call).encode(), + digestmod=hashlib.sha256, + ).hexdigest() + return f"bankid.{qr_start_token}.{elapsed_seconds_since_call}.{qr_auth_code}" diff --git a/docs/api_reference.rst b/docs/api_reference.rst index ff134a6..ba3044c 100644 --- a/docs/api_reference.rst +++ b/docs/api_reference.rst @@ -5,7 +5,7 @@ API Reference ============= Base Client -~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~ .. automodule:: bankid.baseclient :members: @@ -22,6 +22,12 @@ Asynchronous Client .. automodule:: bankid.asyncclient :members: +QR Utils +~~~~~~~~ + +.. automodule:: bankid.qr + :members: + Exceptions ~~~~~~~~~~ .. automodule:: bankid.exceptions diff --git a/docs/examples.rst b/docs/examples.rst index 7f5dcc4..14c5836 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -8,6 +8,9 @@ PyBankID can generate QR codes for you. There is an demo application in the `examples folder of the repo `_ where a Flask application called ``qrdemo`` shows one way to do authentication with animated QR codes. +The QR code content generation is done with the ``generate_qr_code_content`` method on the BankID Client instances, or diectly +through the identically named method in ``bankid.qr`` module. + Below follows the app's README file, for your convenience. QR Authentication Example