Metadata-Version: 2.1
Name: pywarp
Version: 0.0.4
Summary: Python WebAuthn Relying Party library
Home-page: https://github.com/pyauth/pywarp
Author: Andrey Kislyuk
Author-email: kislyuk@gmail.com
License: Apache Software License
Platform: UNKNOWN
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Provides-Extra: test
Requires-Dist: pyjwt (<2,>=1.5.3)
Requires-Dist: cbor2 (<5,>=4.1.2)
Requires-Dist: cryptography (<3,>=2.1.4)
Requires-Dist: requests (<3,>=2.18.4)
Provides-Extra: test
Requires-Dist: coverage; extra == 'test'
Requires-Dist: flake8; extra == 'test'
Requires-Dist: wheel; extra == 'test'

PyWARP: Python Web Authentication Relying Party library
=======================================================

**PyWARP** is an implementation of the W3C `WebAuthn <https://www.w3.org/TR/webauthn/>`_ standard's Relying Party
component in Python. The WebAuthn standard is used to provide advanced authentication security for two-factor,
multifactor and passwordless authentication models through the use of dedicated hardware security keys and biometric
devices such as `Yubico YubiKey <https://www.yubico.com/>`_,
`Google Titan <https://store.google.com/us/product/titan_security_key_kit>`_,
`TPM <https://en.wikipedia.org/wiki/Trusted_Platform_Module>`_, and
`Touch ID <https://en.wikipedia.org/wiki/Touch_ID>`_.

Compared to more basic two-factor standards like HOTP (`RFC 4226 <https://tools.ietf.org/html/rfc4226>`_) and TOTP
(`RFC 6238 <https://tools.ietf.org/html/rfc6238>`_), the
`FIDO U2F <https://en.wikipedia.org/wiki/Universal_2nd_Factor>`_ profile of WebAuthn uses asymmetric cryptography to
avoid using a shared secret design, which strengthens your authentication solution against server-side attacks. Hardware
U2F also sequesters the client secret in a dedicated single-purpose device, which strengthens your clients against
client-side attacks. And by automating scoping of credentials to relying party IDs (application origin/domain names),
U2F adds protection against phishing attacks.

PyWARP implements the *Relying Party* component of WebAuthn. A Relying Party is a server-side application that instructs
the browser (user agent) to use WebAuthn APIs to authenticate its users.

To see an example of PyWARP in action, check the ``examples`` directory. Two demos are included: an
`AWS Chalice <https://github.com/aws/chalice>`_ app and a `Flask <https://github.com/pallets/flask>`_ app.

In addition to reading the `WebAuthn standard <https://www.w3.org/TR/webauthn/>`_, we recommend that implementers read
the `OWASP Authentication Cheat Sheet <https://www.owasp.org/index.php/Authentication_Cheat_Sheet>`_ and
`NIST SP 800-63-3: Digital Authentication Guideline <https://pages.nist.gov/800-63-3/>`_ for a high level overview of
authentication best practices.

Installation
------------
::

    pip install pywarp

PyWARP depends on `cryptography <https://github.com/pyca/cryptography>`_, which in turn requires OpenSSL and CFFI.

Synopsis
--------

.. code-block:: python

    from pywarp import RelyingPartyManager, Credential
    from pywarp.backends import DynamoBackend  # This is an example. See "storage backends" below for other databases.

    rp_id = "myapp.example.com"  # This must match the origin domain of your app, as seen by the browser.
    rp = RelyingPartyManager("PyWARP demo", rp_id=rp_id, credential_storage_backend=DynamoBackend())

    # Get options for navigator.credentials.create() - pass these to your frontend when registering a user
    rp.get_registration_options(email=str)

    # Run the protocol in https://www.w3.org/TR/webauthn/#registering-a-new-credential,
    # then call the credential storage backend to store the credential public key.
    rp.register(attestation_object=bytes, client_data_json=bytes, email=bytes)

    # Get options for navigator.credentials.get() - pass these to your frontend when logging in a user
    rp.get_authentication_options(email=str)

    # Run the protocol in https://www.w3.org/TR/webauthn/#verifying-assertion,
    # calling the credential storage backend to retrieve the credential public key.
    # If no exception is raised, proceed with user login.
    rp.verify(authenticator_data=bytes, client_data_json=bytes, signature=bytes, user_handle=bytes, raw_id=bytes,
              email=bytes)

See `examples/chalice/app.py <examples/chalice/app.py>`_ and
`examples/chalice/chalicelib/index.html <examples/chalice/chalicelib/index.html>`_ (frontend) for a complete example.

Storage backends
----------------

Your application is presumably using an application server like uWSGI, a database backend like MySQL, PostgreSQL or
MongoDB, and maybe a framework like Flask or Django to tie them together. PyWARP makes no assumptions about your
database, schema, or model. Instead, it provides an abstract class (``pywarp.backends.CredentialStorageBackend``)
representing an interface for storing and retrieving WebAuthn credential data for your users.

To deploy PyWARP, declare a subclass of ``CredentialStorageBackend``. In your subclass, implement bindings to your
database, then pass an instance of your subclass to ``pywarp.RelyingPartyManager(credential_storage_backend=...)``:

.. code-block:: python

    class CredentialStorageBackend:
        def __init__(self):
            self.database_client = ...

        def get_credential_by_email(self, email):
            user_record = self.database_client.get(email)
            return Credential(credential_id=user_record["cred_id"],
                              credential_public_key=user_record["cred_pub_key"])

        def save_credential_for_user(self, email, credential):
            self.database_client.update(email, {"cred_id": credential.credential_id,
                                                "cred_pub_key": bytes(credential.public_key)})

        def save_challenge_for_user(self, email, challenge, type):
            self.database_client.update(email, {type + "challenge": challenge})

        def get_challenge_for_user(self, email, type):
            user_record = self.database_client.get(email)
            return user_record[type + "challenge"]

Example: Chalice app
--------------------

The Chalice app example (in the ``examples/chalice`` directory) can be deployed as an `AWS Lambda <TODO>`_ application
when used with conventional AWS account credentials (configured via ``aws configure`` in the `AWS CLI <TODO>`_. This
example uses `DynamoDB <TODO>`_ as a storage backend.

See the `API documentation <https://pywarp.readthedocs.io>`_ for more.

Authors
-------
* Andrey Kislyuk

Links
-----
* `Project home page (GitHub) <https://github.com/pyauth/pywarp>`_
* `Documentation (Read the Docs) <https://pywarp.readthedocs.io/en/latest/>`_
* `Package distribution (PyPI) <https://pypi.python.org/pypi/pywarp>`_
* `Change log <https://github.com/pyauth/pywarp/blob/master/Changes.rst>`_

Bugs
----
Please report bugs, issues, feature requests, etc. on `GitHub <https://github.com/pyauth/pywarp/issues>`_.

License
-------
Licensed under the terms of the `Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0>`_.

.. image:: https://img.shields.io/travis/pyauth/pywarp.svg
        :target: https://travis-ci.org/pyauth/pywarp
.. image:: https://codecov.io/github/pyauth/pywarp/coverage.svg?branch=master
        :target: https://codecov.io/github/pyauth/pywarp?branch=master
.. image:: https://img.shields.io/pypi/v/pywarp.svg
        :target: https://pypi.python.org/pypi/pywarp
.. image:: https://img.shields.io/pypi/l/pywarp.svg
        :target: https://pypi.python.org/pypi/pywarp
.. image:: https://readthedocs.org/projects/pywarp/badge/?version=latest
        :target: https://pywarp.readthedocs.io/


