webauthn_rp

WebAuthn Level 3 RP library.
git clone https://git.philomathiclife.com/repos/webauthn_rp
Log | Files | Refs | README

README.md (13561B)


      1 # `webauthn_rp`
      2 
      3 [<img alt="git" src="https://git.philomathiclife.com/badges/webauthn_rp.svg" height="20">](https://git.philomathiclife.com/webauthn_rp/log.html)
      4 [<img alt="crates.io" src="https://img.shields.io/crates/v/webauthn_rp.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/webauthn_rp)
      5 [<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-webauthn_rp-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/webauthn_rp/latest/webauthn_rp/)
      6 
      7 `webauthn_rp` is a library for _server-side_
      8 [Web Authentication (WebAuthn)](https://www.w3.org/TR/webauthn-3/#sctn-rp-operations) Relying Party
      9 (RP) operations.
     10 
     11 The purpose of a server-side RP library is to be modular so that any client can be used with it as a backend
     12 _including_ native applications—WebAuthn technically only covers web applications; however it's relatively easy
     13 to adapt to native applications as well. It achieves this by not assuming how data is sent to/from the client;
     14 having said that, there are pre-defined serialization formats for "common" deployments which can be used when
     15 [`serde`](#serde) is enabled.
     16 
     17 ## Cargo "features"
     18 
     19 [`custom`](#custom) or both [`bin`](#bin) and [`serde`](#serde) must be enabled; otherwise a `compile_error`
     20  will occur.
     21 
     22 ### `bin`
     23 
     24 Enables binary (de)serialization via `Encode` and `Decode`. Since registered credentials will almost always
     25 have to be saved to persistent storage, _some_ form of (de)serialization is necessary. In the event `bin` is
     26 unsuitable or only partially suitable (e.g., human-readable output is desired), one will need to enable
     27 [`custom`](#custom) to allow construction of certain types (e.g., `AuthenticatedCredential`).
     28 
     29 If possible and desired, one may wish to save the data "directly" to avoid any potential temporary allocations.
     30 For example `StaticState::encode` will return a `Vec` containing hundreds (and possibly thousands in the
     31 extreme case) of bytes if the underlying public key is an RSA key. This additional allocation and copy of data
     32 is obviously avoided if `StaticState` is stored as a
     33 [composite type](https://www.postgresql.org/docs/current/rowtypes.html) or its fields are stored in separate
     34 columns when written to a relational database (RDB).
     35 
     36 ### `custom`
     37 
     38 Exposes functions (e.g., `AuthenticatedCredential::new`) that allows one to construct instances of types that
     39 cannot be constructed when [`bin`](#bin) or [`serde`](#serde) is not enabled.
     40 
     41 ### `serde`
     42 
     43 Enables (de)serialization of data sent to/from the client via [`serde`](https://docs.rs/serde/latest/serde/)
     44 based on the JSON-motivated definitions (e.g.,
     45 [`RegistrationResponseJSON`](https://www.w3.org/TR/webauthn-3/#dictdef-registrationresponsejson)). Since
     46 data has to be sent to/from the client, _some_ form of (de)serialization is necessary. In the event `serde`
     47 is unsuitable or only partially suitable, one will need to enable [`custom`](#custom) to allow construction
     48 of certain types (e.g., `Registration`).
     49 
     50 Code is _strongly_ encouraged to rely on the `Deserialize` implementations as much as possible to reduce the
     51 chances of improperly deserializing the client data.
     52 
     53 Note that clients are free to send data in whatever form works best, so there is no requirement the
     54 JSON-motivated definitions are used even when JSON is sent. This is especially relevant since the JSON-motivated
     55 definitions were only added in [WebAuthn Level 3](https://www.w3.org/TR/webauthn-3/); thus many deployments only
     56 partially conform. Some specific deviations that may require partial customization of deserialization are the
     57 following:
     58 
     59 * [`ArrayBuffer`](https://webidl.spec.whatwg.org/#idl-ArrayBuffer)s encoded using something other than
     60   base64url.
     61 * `ArrayBuffer`s that are encoded multiple times (including the use of different encodings each time).
     62 * Missing fields (e.g.,
     63   [`transports`](https://www.w3.org/TR/webauthn-3/#dom-authenticatorattestationresponsejson-transports)).
     64 * Different field names (e.g., `extensions` instead of
     65   [`clientExtensionResults`](https://www.w3.org/TR/webauthn-3/#dom-registrationresponsejson-clientextensionresults)).
     66 
     67 ### `serde_relaxed`
     68 
     69 Automatically enables [`serde`](#serde) in addition to "relaxed" `Deserialize` implementations
     70 (e.g., `RegistrationRelaxed`). Roughly "relaxed" translates to unknown fields being ignored and only
     71 the fields necessary for construction of the type are required. Case still matters, duplicate fields are still
     72 forbidden, and interrelated data validation is still performed when applicable. This can be useful when one
     73 wants to accommodate non-conforming clients or clients that implement older versions of the spec.
     74 
     75 ### `serializable_server_state`
     76 
     77 Automatically enables [`bin`](#bin) in addition to `Encode` and `Decode` implementations for
     78 `RegistrationServerState` and `AuthenticationServerState`. Less accurate `SystemTime` is used instead of
     79 `Instant` for timeout enforcement. This should be enabled if you don't desire to use in-memory collections to
     80 store the instances of those types.
     81 
     82 Note even when written to persistent storage, an application should still periodically remove expired ceremonies.
     83 If one is using a relational database (RDB); then one can achieve this by storing `ServerState::sent_challenge`,
     84 the `Vec` returned from `Encode::encode`, and `ServerState::expiration` and periodically remove all rows
     85 whose expiration exceeds the current date and time.
     86 
     87 ## Registration and authentication
     88 
     89 Both [registration](https://www.w3.org/TR/webauthn-3/#registration-ceremony) and
     90 [authentication](https://www.w3.org/TR/webauthn-3/#authentication-ceremony) ceremonies rely on "challenges", and
     91 these challenges are inherently temporary. For this reason the data associated with challenge completion can
     92 often be stored in memory without concern for out-of-memory (OOM) conditions. There are several benefits to
     93 storing such data in memory:
     94 
     95 * No data manipulation
     96     * By leveraging move semantics, the data sent to the client cannot be mutated once the ceremony begins.
     97 * Improved timeout enforcement
     98     * By ensuring the same machine that started the ceremony is also used to finish the ceremony, deviation of
     99       system clocks is not a concern. Additionally, allowing serialization requires the use of some form of
    100       cross-platform "timestamp" (e.g., [Unix time](https://en.wikipedia.org/wiki/Unix_time)) which differ in
    101       implementation (e.g., platforms implement leap seconds in different ways) and are often not monotonically
    102       increasing. If data resides in memory, a monotonic `Instant` can be used instead.
    103 
    104 It is for those reasons data like `RegistrationServerState` are not serializable by default and require the
    105 use of in-memory collections (e.g., `FixedCapHashSet`). To better ensure OOM is not a concern, RPs should set
    106 reasonable timeouts. Since ceremonies can only be completed by moving data (e.g.,
    107 `RegistrationServerState::verify`), ceremony completion is guaranteed to free up the memory used—
    108 `RegistrationServerState` instances are only 48 bytes on `x86_64-unknown-linux-gnu` platforms. To avoid issues
    109 related to incomplete ceremonies, RPs can periodically iterate the collection for expired ceremonies and remove
    110 such data. Other techniques can be employed as well to mitigate OOM, but they are application specific and
    111 out-of-scope. If this is undesirable, one can enable [`serializable_server_state`](#serializable_server_state)
    112 so that `RegistrationServerState` and `AuthenticationServerState` implement `Encode` and `Decode`. Another
    113 reason one may need to store this information persistently is for load-balancing purposes where the server that
    114 started the ceremony is not guaranteed to be the server that finishes the ceremony.
    115 
    116 ## Supported signature algorithms
    117 
    118 The only supported signature algorithms are the following:
    119 
    120 * Ed25519 as defined in [RFC 8032 § 5.1](https://www.rfc-editor.org/rfc/rfc8032#section-5.1). This corresponds
    121   to `CoseAlgorithmIdentifier::Eddsa`.
    122 * ECDSA as defined in [SEC 1 Version 2.0 § 4.1](https://www.secg.org/sec1-v2.pdf#subsection.4.1) using SHA-256
    123   as the hash function and NIST P-256 as defined in
    124   [NIST SP 800-186 § 3.2.1.3](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf#%5B%7B%22num%22%3A229%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C70%2C275%2C0%5D)
    125   for the underlying elliptic curve. This corresponds to `CoseAlgorithmIdentifier::Es256`.
    126 * ECDSA as defined in SEC 1 Version 2.0 § 4.1 using SHA-384 as the hash function and NIST P-384 as defined in
    127   [NIST SP 800-186 § 3.2.1.4](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf#%5B%7B%22num%22%3A232%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C70%2C264%2C0%5D)
    128   for the underlying elliptic curve. This corresponds to `CoseAlgorithmIdentifier::Es384`.
    129 * RSASSA-PKCS1-v1_5 as defined in [RFC 8017 § 8.2](https://www.rfc-editor.org/rfc/rfc8017#section-8.2) using
    130   SHA-256 as the hash function. This corresponds to `CoseAlgorithmIdentifier::Rs256`.
    131 
    132 ## Correctness of code
    133 
    134 This library more strictly adheres to the spec than many other similar libraries including but not limited to
    135 the following ways:
    136 
    137 * [CTAP2 canonical CBOR encoding form](https://fidoalliance.org/specs/fido-v2.2-rd-20230321/fido-client-to-authenticator-protocol-v2.2-rd-20230321.html#ctap2-canonical-cbor-encoding-form).
    138 * `Deserialize` implementations requiring _exact_ conformance (e.g., not allowing unknown data).
    139 * More thorough interrelated data validation (e.g., all places a Credential ID exists must match).
    140 * Implement a lot of recommended (i.e., SHOULD) criteria (e.g.,
    141   [User display names conforming to the Nickname Profile as defined in RFC 8266](https://www.w3.org/TR/webauthn-3/#dom-publickeycredentialentity-name)).
    142 
    143 Unfortunately like almost all software, this library has not been formally verified; however great care is
    144 employed in the following ways:
    145 
    146 * Leverage move semantics to prevent mutation of data once in a static state.
    147 * Ensure a great many invariants via types.
    148 * Reduce code duplication.
    149 * Reduce variable mutation allowing for simpler algebraic reasoning.
    150 * `panic`-free code[^note] (i.e., define true/total functions).
    151 * Ensure arithmetic "side effects" don't occur (e.g., overflow).
    152 * Aggressive use of compiler and [Clippy](https://doc.rust-lang.org/stable/clippy/lints.html) lints.
    153 * Unit tests for common cases, edge cases, and error cases.
    154 
    155 ## Cryptographic libraries
    156 
    157 This library does not rely on _any_ sensitive data (e.g., private keys) as only signature verification is
    158 ever performed. This means that the only thing that matters with the libraries used is their algorithmic
    159 correctness and not other normally essential aspects like susceptibility to side-channel attacks. While I
    160 personally believe the libraries that are used are at least as "secure" as alternatives even when dealing with
    161 sensitive data, one only needs to audit the correctness of the libraries to be confident in their use. In fact
    162 [`curve25519_dalek`](https://docs.rs/curve25519-dalek/latest/curve25519_dalek/#backends) has been formally
    163 verified when the [`fiat`](https://github.com/mit-plv/fiat-crypto) backend is used making it _objectively_
    164 better than many other libraries whose correctness has not been proven. Two additional benefits of the library
    165 choices are simpler APIs making it more likely their use is correct and better cross-platform compatibility.
    166 
    167 ## Minimum Supported Rust Version (MSRV)
    168 
    169 This will frequently be updated to be the same as stable. Specifically, any time stable is updated and that
    170 update has "useful" features or compilation no longer succeeds (e.g., due to new compiler lints), then MSRV
    171 will be updated.
    172 
    173 MSRV changes will correspond to a SemVer patch version bump pre-`1.0.0`; otherwise a minor version bump.
    174 
    175 ## SemVer Policy
    176 
    177 * All on-by-default features of this library are covered by SemVer
    178 * MSRV is considered exempt from SemVer as noted above
    179 
    180 ## License
    181 
    182 Licensed under either of
    183 
    184 * Apache License, Version 2.0 ([LICENSE-APACHE](https://www.apache.org/licenses/LICENSE-2.0))
    185 * MIT license ([LICENSE-MIT](https://opensource.org/licenses/MIT))
    186 
    187 at your option.
    188 
    189 ## Contribution
    190 
    191 Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you,
    192 as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
    193 
    194 Before any PR is sent, `cargo clippy` and `cargo t` should be run _for each possible combination of "features"_
    195 using stable Rust. One easy way to achieve this is by building `ci` and invoking it with no commands in the
    196 `webauthn_rp` directory or sub-directories. You can fetch `ci` via `git clone https://git.philomathiclife.com/repos/ci`,
    197 and it can be built with `cargo build --release`. Additionally,
    198 `RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features` should be run to ensure documentation can be built.
    199 
    200 ### Status
    201 
    202 This package is actively maintained and will conform to the
    203 [latest WebAuthn API version](https://www.w3.org/TR/webauthn-3/). Previous versions will not be supported—excluding
    204 bug fixes of course—however functionality will exist to facilitate the migration process from the previous version.
    205 
    206 The crate is only tested on `x86_64-unknown-linux-gnu` and `x86_64-unknown-openbsd` targets, but it should work
    207 on most platforms.
    208 
    209 [^note]: `panic`s related to memory allocations or stack overflow are possible since such issues are not
    210          formally guarded against.