Crate webauthn_rs

source ·
Expand description

Webauthn-rs - Webauthn for Rust Server Applications

Webauthn is a standard allowing communication between servers, browsers and authenticators to allow strong, passwordless, cryptographic authentication to be performed. Webauthn is able to operate with many authenticator types, such as U2F, TouchID, Windows Hello and many more.

This library aims to provide a secure Webauthn implementation that you can plug into your application, so that you can provide Webauthn to your users.

There are a number of focused use cases that this library provides, which are described in the WebauthnBuilder and Webauthn struct.

Getting started

In the simplest case where you just want a password replacement, you should use our passkey flow.

use webauthn_rs::prelude::*;

let rp_id = "example.com";
let rp_origin = Url::parse("https://idm.example.com")
    .expect("Invalid URL");
let mut builder = WebauthnBuilder::new(rp_id, &rp_origin)
    .expect("Invalid configuration");
let webauthn = builder.build()
    .expect("Invalid configuration");

// Initiate a basic registration flow to enroll a cryptographic authenticator
let (ccr, skr) = webauthn
    .start_passkey_registration(
        Uuid::new_v4(),
        "claire",
        "Claire",
        None,
    )
    .expect("Failed to start registration.");

After this point you then need to use finish_passkey_registration, followed by start_passkey_authentication and finish_passkey_authentication

No other authentication factors are needed!

Tutorial

A tutorial on how to use this library is on the project github https://github.com/kanidm/webauthn-rs/tree/master/tutorial

Features

Allow Serialising Registration and Authentication State

During a webauthn registration or authentication ceremony, a random challenge is produced and provided to the client. The full content of what is needed for the server to validate this challenge is stored in the associated registration or authentication state types. This value MUST be persisted on the server. If you store this in a cookie or some other form of client side stored value, the client can replay a previous authentication state and signature without possession of, or interaction with the authenticator, bypassing pretty much all of the guarantees of webauthn. Because of this risk by default these states are not allowed to be serialised which prevents them from accidentally being placed into a cookie.

However there are some safe cases of serialising these values. This includes serialising to a database, or using a cookie “memory store” where the client side cookie is a key into a server-side map or similar. Both of these prevent the replay attack threat.

An alternate but “less good” method to mitigate replay attacks is to associate a very short expiry window to the cookie if you need full client side state, but this may still allow some forms of real time replay attacks to occur.

Enabling the feature danger-allow-state-serialisation allows you to re-enable serialisation of these types, provided you accept and understand the handling risks associated.

This library supports some optional features that you may wish to use. These are all disabled by default as they have risks associated.

Allow Insecure RSA_SHA1

Many Windows Hello credentials are signed with RSA and SHA1. SHA1 is considered broken and should not be trusted in cryptographic contexts. These signatures are used only during attestation, but the credentials themself are generally RSA-SHA256. In some cases this may allow forgery of a credentials attestation, meaning you are unable to trust the integrity of the authenticator.

For the broadest compatibility, and if you do not use attestation (such as passkey only users) you may choose to use RSA SHA1 signed credentials with danger-insecure-rs1 as this has no impact on your system security. For users who use attestation, you should NOT enable this feature as it undermines attestation.

Credential Internals and Type Changes

By default the type wrappers around the keys are opaque. However in some cases you may wish to migrate a key between types (security key to passkey, passwordlesskey to passkey) for example. Alternately, you may wish to access the internals of a credential to implement an alternate serialisation or storage mechanism. In these cases you can access the underlying Credential type via Into and From by enabling the feature danger-credential-internals. The Credential type is exposed via the prelude when this feature is enabled.

User-Presence only SecurityKeys

By default, SecurityKeys will opportunistically enforce User Verification (Such as a PIN or Biometric). This can cause issues with Firefox which only supports CTAP1. An example of this is if you register a SecurityKey on chromium it will be bound to always perform UserVerification for the life of the SecurityKey precluding it’s use on Firefox.

Enabling the feature danger-user-presence-only-security-keys changes these keys to prevent User Verification if possible. However, newer keys will confusingly force a User Verification on registration, but will then not prompt for this during usage. Some user surveys have shown this to confuse users to why the UV is not requested, and it can lower trust in these tokens when they are elevated to be self-contained MFA as the user believes these UV prompts to be unreliable and not verified correctly. In these cases you MUST communicate to the user that the UV may occur on registration and then will not occur again, and that is by design.

Modules

A prelude of types that are used by Webauthn

Structs

An instance of a Webauthn site. This is the main point of interaction for registering and authenticating credentials for users. Depending on your needs, you’ll want to allow users to register and authenticate with different kinds of authenticators.
A constructor for a new Webauthn instance. This accepts and configures a number of site-wide properties that apply to all webauthn operations of this service.