webauthn-ruby turns a Rails server into a WebAuthn Relying Party
WebAuthn ruby server library ― Make your Ruby/Rails web server become a conformant WebAuthn Relying Party
At a glance
- What is it?
- webauthn-ruby implements the server half of the WebAuthn registration and authentication ceremonies, including the cryptographic checks, so a Ruby application can offer passkeys. It suits teams adding passwordless login or a second factor, and it leaves the browser and the authenticator to do their half of the work.
- Who is it for?
- Adopt webauthn-ruby if you run Ruby or Rails and want passkey registration and authentication handled by your own server, with credentials under your control and the cryptographic checks already written. Do not adopt it if you need a client-side-only flow, a native mobile integration, or a service where the authenticator and browser combination is not in your support matrix.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The server half of a passkey ceremony
WebAuthn is a W3C standard for secure public-key authentication on the web, and it is the standard that underpins passkeys, the phishing-resistant replacement for passwords. The difficulty for a server team is that a registration or authentication ceremony is not a form post. The browser mediates a challenge between your server and a hardware or platform authenticator, and the server has to verify the signed response against what it issued.
webauthn-ruby is a server library that takes care of the server-side operations needed to register or authenticate a user's public key credential, a passkey, including the necessary cryptographic checks. Its stated goal is to make your Ruby or Rails web server a functional WebAuthn Relying Party, in the terminology of the specification.
Two things follow from that framing. The library is server side only, so it does nothing for a native app that talks to the platform authenticator APIs directly, and it does not replace the other half of the puzzle. The README is explicit that the registration and authentication ceremonies only fully work when you also have a conforming user agent and authenticator pair, and it lists known conformant combinations such as Chrome on Android 70 and later with the fingerprint based platform authenticator, Edge with the Windows 10 platform authenticator, Firefox for desktop with a Yubico Security Key over USB, and Safari on iOS 13.3 and later with a YubiKey 5 over NFC.
Install is a gem line and a bundle
The gem is called webauthn and it is distributed on RubyGems. For a bundler-managed application the README asks you to add one line to the Gemfile:
gem 'webauthn'and then run:
$ bundleIf you do not use bundler, the gem installs on its own:
$ gem install webauthnThere is no generator and no credential store to set up. The library gives you objects for the two ceremonies and expects your application to decide where the registered credentials live, which is normally a table of user id, credential id, public key and sign count.
If you are moving an existing application from the legacy FIDO U2F JavaScript API to WebAuthn, the README points to a dedicated document, docs/u2f_migration.md, for that path. That file matters more than it sounds: the U2F API and WebAuthn have different ceremony shapes and different credential identifiers, so a migration is not a frontend swap.
Security issues have a named destination. The README asks that vulnerabilities be reported to [email protected], and a SECURITY.md file sits in the repository root next to a CHANGELOG.md.
allowed_origins is the setting that decides where passkeys work
Configuration for a Rails application goes in config/initializers/webauthn.rb, and the block starts with the setting that causes the most integration pain:
WebAuthn.configure do |config|
# This value needs to match `window.location.origin` evaluated by
# the User Agent during registration and authentication ceremonies.
# Multiple origins can be used when needed. Using more than one will imply you MUST configure rp_id explicitely. If you need your credentials to be bound to a single origin but you have more than one tenant, please see [our Advanced Configuration section](https://github.com/cedarcode/webauthn-ruby/blob/master/docs/advanced_configuration.md) instead of adding multiple origins.
config.allowed_origins = ["https://auth.example.com"]The rule is that the value has to match the origin the browser evaluated during the ceremony, which means a mismatch between the domain in your URL and the domain in the configuration is a registration failure rather than a subtle security weakness. The origin includes the scheme, so http and https are different origins.
The comment also warns against the obvious shortcut. Adding several origins is possible, but it means you must configure rp_id explicitly, and if you want credentials bound to one origin while serving several tenants, the README sends you to the advanced configuration document instead. Setting allowed_origins to a list is a decision with security consequences, not a convenience switch.
The rest of the block is small. config.rp_name is the relying party name shown for display purposes, and there is an optional client timeout hint in milliseconds for how long the browser should wait.
Cross-origin iframe verification is disabled by default
The configuration comments spell out one of the more interesting decisions in the library, and they are worth reading in full rather than skimming.
When your app runs inside an iframe or another embedded context, the browser reports a crossOrigin and a topOrigin value. The library does not verify those by default. As the comments put it, when verify_cross_origin is false, any crossOrigin and topOrigin values reported by the browser are ignored, and as a result credentials created or used within a cross-origin iframe are treated as valid.
If you enable the check, you get two options. You can allow only specific top-level origins to embed the ceremony, with each entry matching the browser-reported topOrigin during registration and authentication:
# config.allowed_top_origins = ["https://app.example.com"]or you can forbid cross-origin iframe usage altogether by allowing no origins at all, which rejects creation and authentication whenever crossOrigin is true:
# config.allowed_top_origins = []Setting verify_cross_origin to true without also setting allowed_top_origins has no effect, because the allowed list is ignored while the check is off. The default is defensible for an application that is never embedded, and a hazard for one that is, which is why the setting is worth deciding explicitly rather than inheriting.
Two demo apps and a documented advanced configuration path
The usage section of the README points at working examples rather than writing a long tutorial, which is a reasonable choice for a library whose interesting part is the ceremony protocol.
For a passwordless login in a Rails application, the example lives in the webauthn-rails-demo-app repository. For using the gem as a second factor authenticator instead, the webauthn-2fa-rails-demo repository covers that case. Same library, two very different products: one removes the password entirely, the other adds a hardware-backed factor next to it. The second factor case is the one that changes threat modelling least, and the demo makes it easy to see what the ceremony wiring looks like on the server.
Beyond the demos, the repository carries a docs/ directory with the advanced configuration page and the U2F migration guide referenced above. The advanced configuration document is the recommended path for multi-tenant applications and for applications where different parts of the system authenticate to different subdomains.
The table of contents also reserves a section for attestation statement formats, which is where a relying party decides which authenticator attestations it will accept, and a section on testing your integration, alongside contributing notes. The gem's own repository layout is conventional: lib/ for the code, spec/ with an .rspec file, a .rubocop.yml, a Rakefile, and webauthn.gemspec.
MIT licensed, published to RubyGems, last push 2026-09-03
The licence is MIT, with the text in LICENSE.txt at the repository root, and the gem is published on RubyGems at the webauthn gem page, which is also the project's listed homepage. Conventional Commits are used for the commit history, and the build badge points at a workflow file in the .github directory.
The repository has no GitHub releases, so the version history is the one on RubyGems and the CHANGELOG.md file rather than a list of tagged GitHub releases. The last push to the repository was on 2026-09-03, which is recent enough that the code was being worked on, though it does not by itself say how often a new gem version ships.
The upgrade question for a security library is a different one from the upgrade question for an application dependency. A passkey library sits on the path of an authentication ceremony, so the version you run determines which cryptographic checks and which specification quirks are handled for you. A dependency audit that treats this gem like any other line in a Gemfile.lock understates the exposure.
Editorial conclusion
Adopt webauthn-ruby if you run Ruby or Rails and want passkey registration and authentication handled by your own server, with credentials under your control and the cryptographic checks already written. Do not adopt it if you need a client-side-only flow, a native mobile integration, or a service where the authenticator and browser combination is not in your support matrix. Before you ship, set allowed_origins to the exact origin your users see, decide whether to turn on verify_cross_origin for embedded contexts, and confirm that your relying party identifier covers the subdomains your users authenticate from.
Frequently asked questions
How do I install the webauthn gem?
Add gem 'webauthn' to your application's Gemfile and run bundle, or install it directly with gem install webauthn. The gem is published on RubyGems.
What does the allowed_origins setting do in webauthn-ruby?
It lists the origins the browser is allowed to evaluate during a ceremony, and the value has to match the origin the user agent sees. Using more than one origin means you must configure rp_id explicitly, and the README points to the advanced configuration section for multi-tenant setups.
Is cross-origin iframe verification enabled by default?
No. The configuration comments state that crossOrigin and topOrigin values reported by the browser are ignored by default, so credentials used in a cross-origin iframe are treated as valid. Enabling verify_cross_origin and setting allowed_top_origins turns the check on.
Do I need a specific browser and authenticator to use webauthn-ruby?
The library needs a conforming user agent and authenticator pair for the ceremonies to work fully. The README lists known pairs including Chrome on Android with the platform authenticator, Edge with the Windows 10 platform authenticator, Firefox with a Yubico Security Key over USB, and Safari on iOS 13.3 and later with a YubiKey 5 over NFC.
How do I migrate from the FIDO U2F JavaScript API?
The repository ships a dedicated document, docs/u2f_migration.md, for migrating an existing application from the legacy FIDO U2F JavaScript API to WebAuthn. Separate demo applications also cover passwordless login and two-factor use in Rails.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/cedarcode-webauthn-ruby)Was this useful?