Skip to content

Commit

Permalink
Merge pull request #225 from duo-labs/mm/docs-registration
Browse files Browse the repository at this point in the history
Initial docs content
  • Loading branch information
MasterKale authored Aug 15, 2024
2 parents 6d73560 + c3ca47f commit ff4de8c
Show file tree
Hide file tree
Showing 9 changed files with 223 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ help:
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

livehtml:
sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
sphinx-autobuild --pre-build 'rm -rf build/' "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
9 changes: 9 additions & 0 deletions source/_static/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Theme overrides - alabaster
*/
div.body p, div.body dd, div.body li, div.body blockquote {
-moz-hyphens: none;
-ms-hyphens: none;
-webkit-hyphens: none;
hyphens: none;
}
9 changes: 9 additions & 0 deletions source/authentication.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Authentication

Coming Soon

## Examples

Additional examples of the use of `generate_authentication_options` and `verify_authentication_response` are available here:

<https://github.com/duo-labs/py_webauthn/blob/master/examples/authentication.py>
26 changes: 24 additions & 2 deletions source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,32 @@
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

html_theme = "alabaster"
html_static_path = ["_static"]
html_css_files = ["styles.css"]

# -- Theme configuration -----------------------------------------------------
# https://alabaster.readthedocs.io/en/latest/customization.html

# -- Extension Configuration - MyST Parser
html_theme = "alabaster"
html_theme_options = {
"github_user": "duo-labs",
"github_repo": "py_webauthn",
"description": "Pythonic WebAuthn 🐍",
"github_button": True,
"show_powered_by": False,
"show_relbar_bottom": True,
}
html_sidebars = {
"**": [
"about.html",
"searchfield.html",
"navigation.html",
"relations.html",
]
}

# -- Extension Configuration - MyST Parser -----------------------------------
# https://myst-parser.readthedocs.io/en/latest/configuration.html

myst_enable_extensions = [
"colon_fence",
Expand Down
27 changes: 27 additions & 0 deletions source/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# py_webauthn

[![PyPI](https://img.shields.io/pypi/v/webauthn.svg)](https://pypi.python.org/pypi/webauthn) [![GitHub license](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/duo-labs/py_webauthn/master/LICENSE) ![Pythonic WebAuthn](https://img.shields.io/badge/Pythonic-WebAuthn-brightgreen?logo=python&logoColor=white)

A Python3 implementation of the server-side of the [WebAuthn API](https://www.w3.org/TR/webauthn-2/) focused on making it easy to leverage the power of WebAuthn.

This library supports all FIDO2-compliant authenticators, including security keys, Touch ID, Face ID, Windows Hello, Android biometrics...and pretty much everything else.

## Installation

This module is available on **PyPI**:

`pip install webauthn`

## Requirements

- Python 3.8 and up

```{toctree}
:hidden:
:maxdepth: 2
intro
registration
authentication
passkeys
```
18 changes: 0 additions & 18 deletions source/index.rst

This file was deleted.

39 changes: 39 additions & 0 deletions source/intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Overview

The **py_webauthn** library exposes a small number of core methods from the `webauthn` module:

- `generate_registration_options()`
- `verify_registration_response()`
- `generate_authentication_options()`
- `verify_authentication_response()`

Two additional helper methods are also exposed:

- `options_to_json()`
- `base64url_to_bytes()`

Additional data structures are available on `webauthn.helpers.structs`. These dataclasses are useful for constructing inputs to the methods above, and for providing type hinting to help ensure consistency in the shape of data being passed around.

## Assumptions

The library makes the following assumptions about how a Relying Party that is incorporating this library into their project will interface with the WebAuthn API:

- **JSON** is the preferred data type for transmitting WebAuthn API options from the **server** to the **browser**.
- **JSON** is the preferred data type for transmitting WebAuthn responses from the **browser** to the **server**.
- Bytes are not directly transmittable in either direction as JSON, and so should be encoded to and decoded from **base64url** to avoid introducing any more dependencies than those that [are specified in the WebAuthn spec](https://www.w3.org/TR/webauthn-2/#sctn-dependencies).

## Front End Libraries

py_webauthn is concerned exclusively with the **server** side of supporting WebAuthn. This means that Relying Parties will need to orchestrate calls to WebAuthn in the **browser** in some other way.

Typically this means **manually writing front end JavaScript** to coordinate encoding and decoding certain `bytes` values to and from **base64url** before calling WebAuthn's `navigator.credentials.create()` and `navigator.credentials.get()`.

Relying Parties may also consider **using an existing third-party library** that takes care of all this.

### @simplewebauthn/browser

A great third-party library option is the **@simplewebauthn/browser** library out of the SimpleWebAuthn project:

<https://simplewebauthn.dev/docs/packages/browser>

The methods available in **@simplewebauthn/browser** can accept JSON output from this project without modification, and their return values can be passed as-is into the `credential` argument of this library's response verification methods. See the SimpleWebAuthn docs for more information.
3 changes: 3 additions & 0 deletions source/passkeys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Passkeys

Coming Soon
111 changes: 111 additions & 0 deletions source/registration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Registration

WebAuthn registration ceremonies can be broken up into two operations:

1. Generate WebAuthn API options
2. Verify the WebAuthn response

Typical use of WebAuthn requires that a user account be identified at the time of registration. This can mean:

- The user has successfully logged in via username and password and is proceeding through a prompt to upgrade to using passkeys
- The user has just clicked a magic link to confirm their email address during new account creation
- A logged-in user is adding a passkey to go passwordless on their next login

Regardless of the scenario, the Relying Party should ensure they have **a strong sense of which user is logged in** before proceeding.

## Generate Options

Registration options are created using the following method:

```py
from webauthn import generate_registration_options
from webauthn.helpers.structs import (
AttestationConveyancePreference,
AuthenticatorAttachment,
AuthenticatorSelectionCriteria,
PublicKeyCredentialDescriptor,
ResidentKeyRequirement,
)
from webauthn.helpers.cose import COSEAlgorithmIdentifier

# Simple Options
simple_registration_options = generate_registration_options(
rp_id="example.com",
rp_name="Example Co",
user_name="bob",
)

# Complex Options
complex_registration_options = generate_registration_options(
rp_id="example.com",
rp_name="Example Co",
user_id=bytes([1, 2, 3, 4]),
user_name="Lee",
attestation=AttestationConveyancePreference.DIRECT,
authenticator_selection=AuthenticatorSelectionCriteria(
authenticator_attachment=AuthenticatorAttachment.PLATFORM,
resident_key=ResidentKeyRequirement.REQUIRED,
),
challenge=bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]),
exclude_credentials=[
PublicKeyCredentialDescriptor(
id=b"1234567890",
transports=[
AuthenticatorTransport.INTERNAL,
AuthenticatorTransport.HYBRID,
]
),
],
supported_pub_key_algs=[COSEAlgorithmIdentifier.ECDSA_SHA_512],
timeout=12000,
)
```

[See the docstrings](https://github.com/duo-labs/py_webauthn/blob/2219507f483e5592ec980ec95d97a5d3563fa45b/webauthn/registration/generate_registration_options.py#L42-L69) for details about the various required and optional **kwargs**.

The output from `generate_registration_options()` can be passed into `webauthn.helpers.options_to_json()` to quickly convert them to a `str` value that can be sent to the browser as JSON.

## Verify Response

Registration responses can be verified using the following method:

```py
from webauthn import (
verify_registration_response, # <--
base64url_to_bytes,
)

verification = verify_registration_response(
# Can be a `str` or `dict`
credential={
"id": "...",
"rawId": "...",
"response": {
"attestationObject": "...",
"clientDataJSON": "...",
"transports": ["internal"],
},
"type": "public-key",
"clientExtensionResults": {},
"authenticatorAttachment": "platform",
},
# The value of `options.challenge` from above
expected_challenge=base64url_to_bytes("..."),
expected_origin="https://example.com",
expected_rp_id="example.com",
require_user_verification=True,
)
```

[See the docstrings](https://github.com/duo-labs/py_webauthn/blob/2219507f483e5592ec980ec95d97a5d3563fa45b/webauthn/registration/verify_registration_response.py#L67-L100) for details about the various required and optional **kwargs**.

:::{note}
After verifying a response, store the following values from `verification` above for the logged-in user so that the user can use this passkey later to sign in:

- `verification.credential_id`
- `verification.credential_public_key`
- `verification.sign_count`
- `verification.credential_device_type`
- `verification.credential_backed_up`
- The value of `response.transports` from the JSON passed in as the `credential` kwarg
:::

0 comments on commit ff4de8c

Please sign in to comment.