Crates.io | webauthn_rp |
lib.rs | webauthn_rp |
version | |
source | src |
created_at | 2023-12-29 18:56:39.866901 |
updated_at | 2024-12-07 17:18:48.194392 |
description | Server-side Web Authentication (WebAuthn) Relying Party (RP) API. |
homepage | |
repository | https://git.philomathiclife.com/repos/webauthn_rp/ |
max_upload_size | |
id | 1083560 |
Cargo.toml error: | TOML parse error at line 19, column 1 | 19 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
webauthn_rp
webauthn_rp
is a library for server-side
Web Authentication (WebAuthn) Relying Party
(RP) operations.
The purpose of a server-side RP library is to be modular so that any client can be used with it as a backend
including native applications—WebAuthn technically only covers web applications; however it's relatively easy
to adapt to native applications as well. It achieves this by not assuming how data is sent to/from the client;
having said that, there are pre-defined serialization formats for "common" deployments which can be used when
serde
is enabled.
custom
or both bin
and serde
must be enabled; otherwise a compile_error
will occur.
bin
Enables binary (de)serialization via Encode
and Decode
. Since registered credentials will almost always
have to be saved to persistent storage, some form of (de)serialization is necessary. In the event bin
is
unsuitable or only partially suitable (e.g., human-readable output is desired), one will need to enable
custom
to allow construction of certain types (e.g., AuthenticatedCredential
).
If possible and desired, one may wish to save the data "directly" to avoid any potential temporary allocations.
For example StaticState::encode
will return a Vec
containing hundreds (and possibly thousands in the
extreme case) of bytes if the underlying public key is an RSA key. This additional allocation and copy of data
is obviously avoided if StaticState
is stored as a
composite type or its fields are stored in separate
columns when written to a relational database (RDB).
custom
Exposes functions (e.g., AuthenticatedCredential::new
) that allows one to construct instances of types that
cannot be constructed when bin
or serde
is not enabled.
serde
Enables (de)serialization of data sent to/from the client via serde
based on the JSON-motivated definitions (e.g.,
RegistrationResponseJSON
). Since
data has to be sent to/from the client, some form of (de)serialization is necessary. In the event serde
is unsuitable or only partially suitable, one will need to enable custom
to allow construction
of certain types (e.g., Registration
).
Code is strongly encouraged to rely on the Deserialize
implementations as much as possible to reduce the
chances of improperly deserializing the client data.
Note that clients are free to send data in whatever form works best, so there is no requirement the JSON-motivated definitions are used even when JSON is sent. This is especially relevant since the JSON-motivated definitions were only added in WebAuthn Level 3; thus many deployments only partially conform. Some specific deviations that may require partial customization of deserialization are the following:
ArrayBuffer
s encoded using something other than
base64url.ArrayBuffer
s that are encoded multiple times (including the use of different encodings each time).transports
).extensions
instead of
clientExtensionResults
).serde_relaxed
Automatically enables serde
in addition to "relaxed" Deserialize
implementations
(e.g., RegistrationRelaxed
). Roughly "relaxed" translates to unknown fields being ignored and only
the fields necessary for construction of the type are required. Case still matters, duplicate fields are still
forbidden, and interrelated data validation is still performed when applicable. This can be useful when one
wants to accommodate non-conforming clients or clients that implement older versions of the spec.
serializable_server_state
Automatically enables bin
in addition to Encode
and Decode
implementations for
RegistrationServerState
and AuthenticationServerState
. Less accurate SystemTime
is used instead of
Instant
for timeout enforcement. This should be enabled if you don't desire to use in-memory collections to
store the instances of those types.
Note even when written to persistent storage, an application should still periodically remove expired ceremonies.
If one is using a relational database (RDB); then one can achieve this by storing ServerState::sent_challenge
,
the Vec
returned from Encode::encode
, and ServerState::expiration
and periodically remove all rows
whose expiration exceeds the current date and time.
Both registration and authentication ceremonies rely on "challenges", and these challenges are inherently temporary. For this reason the data associated with challenge completion can often be stored in memory without concern for out-of-memory (OOM) conditions. There are several benefits to storing such data in memory:
Instant
can be used instead.It is for those reasons data like RegistrationServerState
are not serializable by default and require the
use of in-memory collections (e.g., FixedCapHashSet
). To better ensure OOM is not a concern, RPs should set
reasonable timeouts. Since ceremonies can only be completed by moving data (e.g.,
RegistrationServerState::verify
), ceremony completion is guaranteed to free up the memory used—
RegistrationServerState
instances are only 48 bytes on x86_64-unknown-linux-gnu
platforms. To avoid issues
related to incomplete ceremonies, RPs can periodically iterate the collection for expired ceremonies and remove
such data. Other techniques can be employed as well to mitigate OOM, but they are application specific and
out-of-scope. If this is undesirable, one can enable serializable_server_state
so that RegistrationServerState
and AuthenticationServerState
implement Encode
and Decode
. Another
reason one may need to store this information persistently is for load-balancing purposes where the server that
started the ceremony is not guaranteed to be the server that finishes the ceremony.
The only supported signature algorithms are the following:
CoseAlgorithmIdentifier::Eddsa
.CoseAlgorithmIdentifier::Es256
.CoseAlgorithmIdentifier::Es384
.CoseAlgorithmIdentifier::Rs256
.This library more strictly adheres to the spec than many other similar libraries including but not limited to the following ways:
Deserialize
implementations requiring exact conformance (e.g., not allowing unknown data).Unfortunately like almost all software, this library has not been formally verified; however great care is employed in the following ways:
panic
-free code1 (i.e., define true/total functions).This library does not rely on any sensitive data (e.g., private keys) as only signature verification is
ever performed. This means that the only thing that matters with the libraries used is their algorithmic
correctness and not other normally essential aspects like susceptibility to side-channel attacks. While I
personally believe the libraries that are used are at least as "secure" as alternatives even when dealing with
sensitive data, one only needs to audit the correctness of the libraries to be confident in their use. In fact
curve25519_dalek
has been formally
verified when the fiat
backend is used making it objectively
better than many other libraries whose correctness has not been proven. Two additional benefits of the library
choices are simpler APIs making it more likely their use is correct and better cross-platform compatibility.
This will frequently be updated to be the same as stable. Specifically, any time stable is updated and that update has "useful" features or compilation no longer succeeds (e.g., due to new compiler lints), then MSRV will be updated.
MSRV changes will correspond to a SemVer patch version bump pre-1.0.0
; otherwise a minor version bump.
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Before any PR is sent, cargo clippy
and cargo t
should be run for each possible combination of "features"
using stable Rust. One easy way to achieve this is by building ci
and invoking it with no commands in the
webauthn_rp
directory or sub-directories. You can fetch ci
via git clone https://git.philomathiclife.com/repos/ci
,
and it can be built with cargo build --release
. Additionally,
RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features
should be run to ensure documentation can be built.
This package is actively maintained and will conform to the latest WebAuthn API version. Previous versions will not be supported—excluding bug fixes of course—however functionality will exist to facilitate the migration process from the previous version.
The crate is only tested on x86_64-unknown-linux-gnu
and x86_64-unknown-openbsd
targets, but it should work
on most platforms.
panic
s related to memory allocations or stack overflow are possible since such issues are not
formally guarded against. ↩