simple-webauthn

    WebAuthn (FIDO2) implementation for MoonBit - ported from SimpleWebAuthn

    webauthn
    fido2
    authentication
    passkeys
    Download zip
    Author
    Version
    0.2.0
    License
    Apache-2.0 AND MIT
    Last updated
    5 hours ago
    Downloads
    65

    #simple-webauthn for MoonBit

    A WebAuthn (FIDO2/Passkey) library for MoonBit, ported from SimpleWebAuthn.

    #Features

    • Registration: Generate options and verify registration responses
    • Authentication: Generate options and verify authentication responses
    • ES256 Signature Verification: Real cryptographic verification via WebCrypto FFI
    • Browser API: Start registration/authentication ceremonies in JS runtimes
    • Passkey Support: Handles synced passkeys with flexible signCount policies
    • Type-safe: Full MoonBit type safety with detailed error types

    #Installation

    Add the package with the current moon CLI:

    moon add f4ah6o/simple-webauthn@0.2.0

    #Migration from 0.1.x

    Version 0.2.0 vendors the CBOR implementation because the published mizchi/cbor@0.1.1 source is incompatible with the current MoonBit compiler. AttestationObject.att_stmt therefore changes from mizchi/cbor.CborValue to f4ah6o/simple-webauthn/cbor.CborValue. Downstream code that directly imports the CBOR package should upgrade the dependency and replace the import in its moon.pkg with:

    moon add --upgrade f4ah6o/simple-webauthn@0.2.0

    import {
    "f4ah6o/simple-webauthn/cbor" @cbor,
    }

    The WebAuthn verification APIs and validation behavior are unchanged.

    #Quick Start

    #Registration Flow

    // 1. Generate registration options (server)
    let input = @server.GenerateRegistrationOptionsInput::new(
    "ACME Corp", // RP name
    "example.com", // RP ID
    "johndoe", // username
    user_display_name=Some("John Doe"),
    )
    let options = @server.generate_registration_options(input)
    // Send options.to_json() to client

    // 2. Verify registration response (server)
    let verify_options = @server.VerifyRegistrationOptions::new(
    challenge_bytes, // The challenge you sent
    "https://example.com", // Expected origin
    "example.com", // Expected RP ID
    )
    let result = @server.verify_registration_response(
    client_data_json, // From client response
    attestation_object, // From client response
    verify_options,
    ) catch {
    e => // Handle error
    }
    // Store: result.credential_id, result.credential_public_key, result.sign_count

    #Authentication Flow

    // 1. Generate authentication options (server)
    let input = @server.GenerateAuthenticationOptionsInput::new(
    rp_id=Some("example.com"),
    )
    let options = @server.generate_authentication_options(input)
    // Send options.to_json() to client

    // 2. Verify authentication response (server) - async version with real crypto
    let credential = @server.AuthenticatorCredential::new(
    stored_credential_id,
    stored_public_key,
    stored_sign_count,
    )
    let verify_options = @server.VerifyAuthenticationOptions::new(
    challenge_bytes,
    "https://example.com",
    "example.com",
    credential,
    )
    let result = @server.verify_authentication_response_async(
    credential_id,
    client_data_json,
    authenticator_data,
    signature,
    verify_options,
    )
    match result {
    Ok(verified) => // Update stored_sign_count = verified.new_sign_count
    Err(e) => // Handle error
    }

    #SignCount Policy

    Control how signature counters are validated to detect cloned authenticators:

    let options = @server.VerifyAuthenticationOptions::new(...)
    .with_sign_count_policy_strict() // Counter must always increase
    // OR
    .with_sign_count_policy_permissive() // Never fail (log warnings externally)
    // Default: AllowZero - both 0 is OK, otherwise must increase

    PolicyBehaviorUse Case
    StrictCounter must always increaseHigh-security with hardware keys
    AllowZero (default)Allow both counters = 0Most applications, supports synced passkeys
    PermissiveNever fail on counterPrefer availability over clone detection

    #Project Structure

    src/ ├── browser/ # Browser-side API (start registration/authentication) ├── types/ # WebAuthn type definitions (COSE, credentials, etc.) ├── helpers/ # Parsing utilities (base64url, clientData, authenticatorData) ├── crypto/ # Cryptographic operations (SHA-256, ES256 via WebCrypto FFI) └── server/ # Main API (generate/verify for registration & authentication)

    #API Reference

    #Registration

    • generate_registration_options(input) - Create options for navigator.credentials.create()
    • verify_registration_response(clientData, attestation, options) - Verify and extract credential

    #Authentication

    • generate_authentication_options(input) - Create options for navigator.credentials.get()
    • verify_authentication_response_async(...) - Verify with real ES256 signature verification
    • verify_authentication_response(...) - Sync version (signature verification stub)

    #Browser

    • browser_supports_webauthn() - Check if the runtime provides WebAuthn APIs
    • platform_authenticator_is_available() - Check for built-in platform authenticators
    • browser_supports_webauthn_autofill() - Check conditional UI/autofill support
    • start_registration(input) - Run browser registration and return RegistrationResponseJSON
    • start_authentication(input) - Run browser authentication and return AuthenticationResponseJSON
    • cancel_ceremony() - Abort an active browser WebAuthn ceremony

    #Error Types

    • RegistrationVerifyError - Detailed registration failure reasons
    • AuthenticationVerifyError - Detailed authentication failure reasons
    • BrowserError - Browser-side ceremony and runtime errors

    #Development

    just # check + test just fmt # format code just check # type check just test # run tests

    #Current Limitations

    • Only ES256 (P-256) signature verification implemented
    • Packed attestation verification not yet implemented (fmt="none" works)

    #License

    Project source: Apache-2.0. The vendored CBOR implementation and tests are MIT-licensed; see LICENSE-MIT and NOTICE.