Skip to content

Commit

Permalink
Documentation update
Browse files Browse the repository at this point in the history
  • Loading branch information
hbldh committed Mar 22, 2024
1 parent 024b7cb commit beb4e0c
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 58 deletions.
4 changes: 2 additions & 2 deletions bankid/asyncclient.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from typing import Optional, Tuple, Dict, Any, Awaitable
from typing import Optional, Tuple, Dict, Any

import httpx

from bankid.base import BankIDClientBaseclass
from bankid.baseclient import BankIDClientBaseclass
from bankid.exceptions import get_json_error_class


Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion bankid/syncclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import httpx

from bankid.base import BankIDClientBaseclass
from bankid.baseclient import BankIDClientBaseclass
from bankid.exceptions import get_json_error_class


Expand Down
18 changes: 15 additions & 3 deletions docs/api_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,22 @@
API Reference
=============

:mod:`bankid.jsonclient` -- Clients
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:mod:`bankid.syncclient` -- Base Client (parent)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. automodule:: bankid.baseclient
:members:

:mod:`bankid.syncclient` -- Synchronous Client
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. automodule:: bankid.syncclient
:members:

:mod:`bankid.asyncclient` -- Asynchronous Client
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. automodule:: bankid.jsonclient
.. automodule:: bankid.asyncclient
:members:

:mod:`bankid.exceptions` -- Exceptions
Expand Down
2 changes: 1 addition & 1 deletion docs/certutils.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ into one certificate and one key part and converts it from
`.p12 or .pfx <https://en.wikipedia.org/wiki/PKCS_12>`_ format to
`pem <https://en.wikipedia.org/wiki/X.509#Certificate_filename_extensions>`_.
These can then be used for testing purposes, by sending in ``test_server=True``
keyword in the :py:class:`~BankIDClient` or :py:class:`~BankIDJSONClient`.
keyword in the :py:class:`~BankIDClient` or :py:class:`~BankIdAsyncClient`.


Splitting certificates
Expand Down
79 changes: 60 additions & 19 deletions docs/examples.rst
Original file line number Diff line number Diff line change
@@ -1,30 +1,71 @@
.. _examples:

===================
Generating QR codes
-------------------
===================

PyBankID cannot generate QR codes for you, but there is an example application in the
PyBankID can generate QR codes for you. There is an example application in the
`examples folder of the repo <https://github.com/hbldh/pybankid/tree/master/examples>`_ where a
Flask application called ``qrdemo`` shows one way to do authentication with animated QR codes.

The content for the QR code is generated by this method:
Below follows the app's README file:

.. code-block:: python
QR Authentication Example
-------------------------

import hashlib
import hmac
from math import floor
import time
Making a simple authentication via QR code solution using Flask, Flask-Caching and PyBankID.

def generate_qr_code_content(qr_start_token: str, start_t: float, qr_start_secret: str):
"""Given QR start token, time.time() when initiated authentication call was made and the
QR start secret, calculate the current QR code content to display.
"""
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}"
Running the application
~~~~~~~~~~~~~~~~~~~~~~~

1. Navigate your terminal to the same folder that this README resides in.
2. Create a virtualenv: ``python -m venv .venv``
3. Activate it.
4. Install requirements: ``pip install -r requirements.txt``
5. Run Flask app:

1. From Bash:

```bash
$ export FLASK_APP=qrdemo.app:app
$ flask run -h 0.0.0.0
```
2. From Powershell:

```powershell
> $env:FLASK_APP = "qrdemo.app:app"
> flask run -h 0.0.0.0
```

The app can now be accessed from the running computer on ``http://127.0.0.1:5000``, ``http://localhost:5000`` or from an
external device on the same network on ``http://<ip for the running computer>:5000``.


Basic workflow
~~~~~~~~~~~~~~

These are the steps that the application takes:

1. Ask the user for Swedish Personal Identity Number (PN) or initiate an authentication without.
2. Upon POSTing that PN to the backend, initiate a BankID ``authenticate`` session. This generates tokens that
one can create QR codes from using the ``generate_qr_code_content`` method.
3. Continuously update the QR code according to the description in the BankID Relying Party Guidelines
Version: 3.6 (see below, Chapter 4). The new QR code content to display MUST be fetched from the backend since
the ``qrStartSecret`` must never be shown to the user for the authentication to be trustworthy.
4. Also make ``collect`` calls to the BankID servers continuously and monitor if signing is complete or failed.
5. Redirect when complete or failed.


Missing components
~~~~~~~~~~~~~~~~~~

There are a few shortcuts taken here:

- There is no error handling of ``status: failed`` results when collecting the authentication response.
- There is no ``Recommended User Messages (RFA)`` handling. It merely displays the ``status`` and ``hintCode`` from the collect response.
- The Cache is a memory cache on this single instance web app.

References
~~~~~~~~~~

[BankID Integration Guide](https://www.bankid.com/en/utvecklare/guider/teknisk-integrationsguide/)
66 changes: 39 additions & 27 deletions docs/get_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Getting Started
===============

PyBankID use BankID JSON API version 5.1 released in April 2020.
PyBankID use BankID JSON API version 6.0 released in May 2023.

Installation
------------
Expand All @@ -19,11 +19,11 @@ Dependencies

PyBankID makes use of the following external packages:

* `httpx==0.24.1 <https://www.python-httpx.org/>`_
* `importlib-resources==5.12.0 <https://importlib-resources.readthedocs.io/>`_
* `httpx<https://www.python-httpx.org/>`_
* `importlib-resources>=5.12.0 <https://importlib-resources.readthedocs.io/>`_

Using the client
----------------------
----------------

PyBankID provide both a synchronous and an asynchronous client for
communication with BankID services. Example below will use the asynchronous
Expand All @@ -34,7 +34,7 @@ Get started by importing and initializing the client:
.. code-block:: python
>>> from bankid import AsyncBankIDJSONClient
>>> client = AsyncBankIDJSONClient(certificates=(
>>> client = BankIdAsyncClient(certificates=(
... 'path/to/certificate.pem',
... 'path/to/key.pem',
... ))
Expand All @@ -48,8 +48,7 @@ is initiated as such:

.. code-block:: python
>>> await client.authenticate(end_user_ip='194.168.2.25',
... personal_number="YYYYMMDDXXXX")
>>> await client.authenticate(end_user_ip='194.168.2.25')
{
'orderRef': 'ee3421ea-2096-4000-8130-82648efe0927',
'autoStartToken': 'e8df5c3c-c67b-4a01-bfe5-fefeab760beb',
Expand All @@ -61,38 +60,55 @@ and a sign order is initiated in a similar fashion:

.. code-block:: python
>>> await client.sign(end_user_ip='194.168.2.25',
... user_visible_data="The information to sign.",
... personal_number="YYYYMMDDXXXX")
>>> await client.sign(
... end_user_ip='194.168.2.25',
... user_visible_data="The information to sign."
...)
{
'orderRef': 'ee3421ea-2096-4000-8130-82648efe0927',
'autoStartToken': 'e8df5c3c-c67b-4a01-bfe5-fefeab760beb',
'qrStartToken': '01f94e28-857f-4d8a-bf8e-6c5a24466658',
'qrStartSecret': 'b4214886-3b5b-46ab-bc08-6862fddc0e06'
}
Since we are using BankID ``v5.1`` JSON API, the `personal_number` can now be omitted when calling
`authenticate` and `sign`. See `BankID Relying Party Guidelines <https://www.bankid.com/utvecklare/rp-info>`_
for more information about this.
If you want to ascertain that only one individual can authenticate or sign, you can
specify this using the ``requirement`` keyword:

.. code-block:: python
>>> await client.sign(
... end_user_ip='194.168.2.25',
... user_visible_data="The information to sign."
... requirement={"personalNumber": "YYYYMMDDXXXX"}
...)
{
'orderRef': 'ee3421ea-2096-4000-8130-82648efe0927',
'autoStartToken': 'e8df5c3c-c67b-4a01-bfe5-fefeab760beb',
'qrStartToken': '01f94e28-857f-4d8a-bf8e-6c5a24466658',
'qrStartSecret': 'b4214886-3b5b-46ab-bc08-6862fddc0e06'
}
If someone else than the one you specified tries to authenticate or sign, the
BankID app will state that the request is not intended for the user.

The status of an order can then be studied by polling
with the ``collect`` method using the received ``orderRef``:

.. code-block:: python
>>> await client.collect(order_ref="a9b791c3-459f-492b-bf61-23027876140b")
>>> await client.collect("a9b791c3-459f-492b-bf61-23027876140b")
{
'hintCode': 'outstandingTransaction',
'orderRef': 'a9b791c3-459f-492b-bf61-23027876140b',
'status': 'pending'
}
>>> await client.collect(order_ref="a9b791c3-459f-492b-bf61-23027876140b")
>>> await client.collect("a9b791c3-459f-492b-bf61-23027876140b")
{
'hintCode': 'userSign',
'orderRef': 'a9b791c3-459f-492b-bf61-23027876140b',
'status': 'pending'
}
>>> await client.collect(order_ref="a9b791c3-459f-492b-bf61-23027876140b")
>>> await client.collect("a9b791c3-459f-492b-bf61-23027876140b")
{
'completionData': {
'cert': {
Expand All @@ -116,31 +132,27 @@ with the ``collect`` method using the received ``orderRef``:
}
Please note that the ``collect`` method should be used sparingly: in the
`BankID Relying Party Guidelines <https://www.bankid.com/utvecklare/rp-info>`_
`BankID Integration Guide <https://www.bankid.com/en/utvecklare/guider/teknisk-integrationsguide>`_
it is specified that *"collect should be called every two seconds and must not be
called more frequent than once per second"*.

Synchronous client
----------------------
------------------

The synchronous client is used in the same way as the asynchronous client, but the
methods are blocking. The synchronous client call the aynchronous client under the
hood.
methods are blocking.

The asynchronous guide above can be used as a reference for the synchronous client
as well, by simply removing the `await` keyword.
as well, by simply removing the ``await`` keyword.

.. code-block:: python
>>> from bankid import BankIDJSONClient
>>> client = BankIDJSONClient(certificates=(
>>> from bankid import BankIdClient
>>> client = BankIdClient(certificates=(
... 'path/to/certificate.pem',
... 'path/to/key.pem',
... ))
>>> client.authenticate(
... end_user_ip='194.168.2.25',
... personal_number="YYYYMMDDXXXX",
... )
>>> client.authenticate(end_user_ip='194.168.2.25')
{
'orderRef': 'ee3421ea-2096-4000-8130-82648efe0927',
'autoStartToken': 'e8df5c3c-c67b-4a01-bfe5-fefeab760beb',
Expand Down
9 changes: 7 additions & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@ providing authentication and signing functionality to end users. This package
provides a simplifying interface for initiating authentication
and signing orders and then collecting the results from the BankID servers.

The only supported BankID API version supported by PyBankID from version 1.0.0
is v6.0, which means that the Secure Start solution is the only supported way
of providing BankID services. PyBankID versions prior to 1.0.0 will not
work after 1st of May 2024.

If you intend to use PyBankID in your project, you are advised to read
the `BankID Relying Party Guidelines
<https://www.bankid.com/utvecklare/rp-info>`_ before
the `BankID Integration Guide
<https://www.bankid.com/en/utvecklare/guider/teknisk-integrationsguide>`_ before
doing anything else. There, one can find information
about how the BankID methods are defined and how to use them.

Expand Down
5 changes: 2 additions & 3 deletions examples/qrdemo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ external device on the same network on `http://<ip for the running computer>:500

These are the steps that the application takes:

1. Ask the user for Swedish Personal Identity Number (PN).
1. Ask the user for Swedish Personal Identity Number (PN) or initiate an authentication without.
2. Upon POSTing that PN to the backend, initiate a BankID `authenticate` session. This generates tokens that
one can create QR codes from using the `generate_qr_code_content` method.
3. Continuously update the QR code according to the description in the BankID Relying Party Guidelines
Expand All @@ -48,5 +48,4 @@ There are a few shortcuts taken here:

## References

[BankID Relying Party Guidelines
Version: 3.6](https://www.bankid.com/assets/bankid/rp/bankid-relying-party-guidelines-v3.6.pdf)
[BankID Integration Guide](https://www.bankid.com/en/utvecklare/guider/teknisk-integrationsguide/)

0 comments on commit beb4e0c

Please sign in to comment.