Skip to main content

BankID Relying Party client for Python

Project description

https://github.com/hbldh/pybankid/workflows/Build%20and%20Test/badge.svg Documentation Status http://img.shields.io/pypi/v/pybankid.svg http://img.shields.io/pypi/l/pybankid.svg https://coveralls.io/repos/github/hbldh/pybankid/badge.svg?branch=master

PyBankID is a client for providing BankID services as a Relying Party, i.e. 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.

If you intend to use PyBankID in your project, you are advised to read the BankID Relying Party Guidelines before doing anything else. There, one can find information about how the BankID methods are defined and how to use them.

Installation

PyBankID can be installed though pip:

pip install pybankid

Usage

BankIDJSONClient is the client to be used to communicate with the BankID service. It uses the JSON 5.1 API released in April 2020.

JSON client

>>> from bankid import BankIDJSONClient
>>> client = BankIDJSONClient(certificates=('path/to/certificate.pem',
                                            'path/to/key.pem'))

Connection to production server is the default in the client. If test server is desired, send in the test_server=True keyword in the init of the client.

When using the JSON client, authentication and signing calls requires the end user’s ip address to be included in all calls. An authentication order is initiated as such:

>>> client.authenticate(end_user_ip='194.168.2.25',
                        personal_number="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'
}

and a sign order is initiated in a similar fashion:

>>> client.sign(end_user_ip='194.168.2.25',
                user_visible_data="The information to sign.",
                personal_number="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'
}

Since the BankIDJSONClient is using the BankID v5 JSON API, the personal_number can now be omitted when calling authenticate and sign. See BankID Relying Party Guidelines for more information about this.

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

>>> client.collect(order_ref="a9b791c3-459f-492b-bf61-23027876140b")
{
    'hintCode': 'outstandingTransaction',
    'orderRef': 'a9b791c3-459f-492b-bf61-23027876140b',
    'status': 'pending'
}
>>> client.collect(order_ref="a9b791c3-459f-492b-bf61-23027876140b")
{
    'hintCode': 'userSign',
    'orderRef': 'a9b791c3-459f-492b-bf61-23027876140b',
    'status': 'pending'
}
>>> client.collect(order_ref="a9b791c3-459f-492b-bf61-23027876140b")
{
    'completionData': {
        'cert': {
            'notAfter': '1581289199000',
            'notBefore': '1518130800000'
        },
        'device': {
            'ipAddress': '0.0.0.0'
        },
        'ocspResponse': 'MIIHegoBAKCCB[...]',
        'signature': 'PD94bWwgdmVyc2lv[...]',
        'user': {
            'givenName': 'Namn',
            'name': 'Namn Namnsson',
            'personalNumber': 'YYYYMMDDXXXX',
            'surname': 'Namnsson'
        }
    },
    'orderRef': 'a9b791c3-459f-492b-bf61-23027876140b',
    'status': 'complete'
}

Please note that the collect method should be used sparingly: in the BankID Relying Party Guidelines it states that “collect should be called every two seconds and must not be called more frequent than once per second”.

PyBankID and QR code

PyBankID cannot generate QR codes for you, but there is an example 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 content for the QR code is generated by this method:

import hashlib
import hmac
from math import floor
import time

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}"

Certificates

Production certificates

If you want to use BankID in a production environment, then you will have to purchase this service from one of the selling banks. They will then provide you with a certificate that can be used to authenticate your company/application with the BankID servers.

This certificate has to be processed somewhat to be able to use with PyBankID, and how to do this depends on what the selling bank provides you with.

Test certificate

The certificate to use when developing against the BankID test servers can be obtained through PyBankID:

>>> import os
>>> import bankid
>>> dir_to_save_cert_and_key_in = os.path.expanduser('~')
>>> cert_and_key = bankid.create_bankid_test_server_cert_and_key(
    dir_to_save_cert_and_key_in)
>>> print(cert_and_key)
['/home/hbldh/certificate.pem', '/home/hbldh/key.pem']
>>> client = bankid.BankIDJSONClient(
    certificates=cert_and_key, test_server=True)

Testing

The PyBankID solution can be tested with pytest:

py.test

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pybankid-0.14.0.tar.gz (40.6 kB view hashes)

Uploaded Source

Built Distribution

pybankid-0.14.0-py2.py3-none-any.whl (27.8 kB view hashes)

Uploaded Python 2 Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page