Passkey Origin Validator

August 11, 2026 · View on GitHub

A tool for validating passkey/WebAuthn origin constraints in .well-known/webauthn endpoints. This tool is based on the Chromium project's implementation of WebAuthn security checking and helps ensure that your WebAuthn implementation follows the same constraints as browsers.

For detailed information about the project background, label definition, and technical details, please see project_status.md.

Installation and Dependencies

Dependencies

These dependencies will be automatically installed when running make deps.

Building

# Get dependencies
make deps

# Build the application
make build

# Clean build artifacts
make clean

# Run tests
make test

Validation Rules

The validator follows the same rules Chromium applies to Related Origin Requests:

  1. JSON structure: The .well-known/webauthn file must be a JSON object containing an origins array.

  2. Label definition: A "label" is the right-most label of an origin's registrable domain (eTLD+1). The host is first reduced to its eTLD+1 — which strips any subdomains — and the label is the portion before the first dot:

    Origin hostLabel
    example.comexample
    test.example.orgexample
    login.example.co.ukexample

    Origins with no registrable domain (IP addresses, bare public suffixes) are skipped, as they are in Chromium.

  3. Label limit: At most 5 unique labels are processed per .well-known file. Origins beyond that limit are not matched, and a failed validation reports BAD_RELYING_PARTY_ID_NO_JSON_MATCH_HIT_LIMITS.

  4. Origin matching: Origins are compared as same-origin — scheme, host, and port — with default ports normalized, so https://example.com and https://example.com:443 are equivalent.

  5. Size limit: Response bodies are limited to 256KB.

  6. Timeout: HTTP requests time out after 10 seconds.

Command Reference

The tool provides several commands and flags to validate WebAuthn origin constraints. Here's a comprehensive guide to using each command:

Global Flags

These flags can be used with any command:

FlagDescription
--config <file>Config file (default is $HOME/.passkey-origin-validator.yaml)
--debugEnable debug logging
--file <file>Use a local JSON file instead of fetching from a domain
--exampleRun with example data for testing
--version, -vPrint version information and exit

Count Command

The count command fetches the .well-known/webauthn endpoint for a given domain, parses the JSON response, and counts the number of unique labels.

Usage:

passkey-origin-validator count [domain]

Arguments:

  • domain (optional): The domain to check. If not provided, defaults to webauthn.io.

Examples:

# Count labels for default domain (webauthn.io)
./build/passkey-origin-validator count

# Count labels with debug logging
./build/passkey-origin-validator count --debug

# Count labels for specific domain
./build/passkey-origin-validator count example.com

# Count labels from local file
./build/passkey-origin-validator count --file ./test.json

Using with Makefile:

# Count labels for default domain (webauthn.io)
make run

# Count labels with debug logging
make run DEBUG=true

# Count labels for specific domain
make run DOMAIN=google.com

# Count labels from local file
make run FILE=./test.json

Validate Command

The validate command checks if a caller origin is authorized by a domain's .well-known/webauthn file.

Usage:

passkey-origin-validator validate [domain] --origin <origin>

Arguments:

  • domain (optional): The domain to check. If not provided, defaults to webauthn.io.

Required Flags:

Examples:

# Validate origin against default domain
./build/passkey-origin-validator validate --origin https://example.com

# Validate origin against specific domain
./build/passkey-origin-validator validate --origin https://example.com google.com

# Validate origin against local file
./build/passkey-origin-validator validate --origin https://example.com --file ./test.json

Using with Makefile:

# Validate origin against default domain
make validate ORIGIN=https://example.com

# Validate origin against specific domain
make validate ORIGIN=https://example.com DOMAIN=google.com

# Validate origin against local file
make validate ORIGIN=https://example.com FILE=./test.json

Validation statuses:

StatusMeaning
SUCCESSThe caller origin is authorized
BAD_RELYING_PARTY_ID_JSON_PARSE_ERRORThe response was not valid JSON, or had no origins array
BAD_RELYING_PARTY_ID_NO_JSON_MATCHNo listed origin matched the caller origin
BAD_RELYING_PARTY_ID_NO_JSON_MATCH_HIT_LIMITSNo match, and the 5-label limit was reached before all origins could be considered

Example Data

You can run the tool with example data to see how it works without making actual HTTP requests:

# Run with example data
./build/passkey-origin-validator --example

# Using Makefile
make example

This will demonstrate the functionality with predefined test cases, showing both successful and failed validations.

Configuration

The tool can be configured using a YAML configuration file. By default, it looks for a file named .passkey-origin-validator.yaml in your home directory. You can specify a different configuration file using the --config flag.

Configuration File Format

The configuration file uses YAML format and supports the following options:

OptionTypeDescription
debugbooleanEnable debug logging
default_domainstringDefault domain to check if not specified
filestringUse a local JSON file instead of fetching from a domain
examplebooleanRun with example data for testing
originstringDefault caller origin to validate (for validate command)
timeoutintegerHTTP request timeout in seconds
max_labelsintegerMaximum number of labels allowed

Sample Configuration File

A sample configuration file is provided in the repository as sample-config.yaml. You can copy this file to your home directory and customize it:

# Copy the sample config to your home directory
cp sample-config.yaml ~/.passkey-origin-validator.yaml

Here's the content of the sample configuration file:

# Sample configuration file for passkey-origin-validator
# Save this as $HOME/.passkey-origin-validator.yaml or specify with --config flag

# Enable debug logging
debug: false

# Default domain to check if not specified
default_domain: "https://webauthn.io"

# Use a local JSON file instead of fetching from a domain
# file: "./test.json"

# Run with example data for testing
example: false

# Default caller origin to validate (for validate command)
# origin: "https://example.com"

# HTTP request timeout in seconds
timeout: 10

# Maximum number of labels allowed
max_labels: 5

Using the Configuration File

To use the configuration file:

  1. Create a YAML file with your desired configuration options
  2. Save it as .passkey-origin-validator.yaml in your home directory, or
  3. Specify the path to your config file with the --config flag:
./build/passkey-origin-validator --config /path/to/your/config.yaml count

Configuration values in the file can be overridden by command-line flags. For example, if your config file has debug: false but you run with --debug, debug logging will be enabled for that run.

Debugging

The tool provides debug logging that can be enabled with the --debug flag or by setting DEBUG=true when using the Makefile. Debug logging provides additional information about:

  • The domain being tested
  • The maximum number of labels allowed
  • The number of unique labels found
  • The list of labels found
  • Whether the number of labels exceeds the limit
  • JSON parsing details

Example:

# Enable debug logging with direct command
./build/passkey-origin-validator count --debug

# Enable debug logging with Makefile
make run DEBUG=true

Exit Status

The tool returns different exit codes depending on the result:

Exit CodeDescription
0Success (number of labels is within the limit)
1Error (failed to fetch or parse the .well-known/webauthn endpoint)
2Warning (number of labels exceeds the limit)
3Validation failure (caller origin is not authorized)

Using as a Go Library

The validation logic lives in internal/counter and can be used from Go code within this module:

status := counter.ValidateWellKnownJSON("https://example.com", jsonBytes)
if status != counter.StatusSuccess {
    // handle the failure — see the validation status table above
}

CI/CD Pipeline

This project uses GitHub Actions for automated testing and releasing. The workflow is configured in the .github/workflows/ci.yml file and consists of two jobs:

  1. Test Job: Runs the project's tests on every pull request and commit to the master branch.
  2. Release Job: Creates a release binary using GoReleaser when a tag is pushed to the repository.

Creating a Release

To create a new release:

  1. Ensure all your changes are committed and pushed to the master branch
  2. Create and push a new tag:
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0

This will trigger the release job in the GitHub Actions workflow, which will:

  • Build binaries for multiple platforms (Linux, macOS, Windows)
  • Create archives of the binaries
  • Generate checksums
  • Create a GitHub release with the binaries and changelog

The release configuration is defined in the .goreleaser.yml file.

License

This project is licensed under the MIT License - see the LICENSE file for details.