{"id":33916581,"url":"https://github.com/cedarcode/devise-webauthn","last_synced_at":"2026-02-10T18:10:27.700Z","repository":{"id":324269782,"uuid":"183835665","full_name":"cedarcode/devise-webauthn","owner":"cedarcode","description":"A devise extension for authentication with passkeys and two factor authentication with security keys","archived":false,"fork":false,"pushed_at":"2026-02-09T19:47:39.000Z","size":389,"stargazers_count":27,"open_issues_count":15,"forks_count":0,"subscribers_count":6,"default_branch":"master","last_synced_at":"2026-02-09T23:16:28.592Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://devise-webauthn.cedarcode.com/","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cedarcode.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["cedarcode"]}},"created_at":"2019-04-28T00:48:54.000Z","updated_at":"2026-02-06T20:34:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cedarcode/devise-webauthn","commit_stats":null,"previous_names":["cedarcode/devise-webauthn"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/cedarcode/devise-webauthn","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedarcode%2Fdevise-webauthn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedarcode%2Fdevise-webauthn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedarcode%2Fdevise-webauthn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedarcode%2Fdevise-webauthn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cedarcode","download_url":"https://codeload.github.com/cedarcode/devise-webauthn/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cedarcode%2Fdevise-webauthn/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29310121,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-10T17:48:59.043Z","status":"ssl_error","status_checked_at":"2026-02-10T17:45:37.240Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-12T07:24:31.262Z","updated_at":"2026-02-10T18:10:27.695Z","avatar_url":"https://github.com/cedarcode.png","language":"Ruby","funding_links":["https://github.com/sponsors/cedarcode"],"categories":[],"sub_categories":[],"readme":"# Devise::Webauthn\n[![Gem Version](https://badge.fury.io/rb/devise-webauthn.svg)](https://badge.fury.io/rb/devise-webauthn)\n\nDevise::Webauthn is a [Devise](https://github.com/heartcombo/devise) extension that adds [WebAuthn](https://www.w3.org/TR/2025/WD-webauthn-3-20250127/) support to your Rails application, allowing users to authenticate with [passkeys](https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#passkey) and use [security keys](https://www.w3.org/TR/webauthn-3/#server-side-credential) for two factor authentication.\n\n## Requirements\n\n- **Ruby**: 2.7+\n- **JavaScript**: This gem includes WebAuthn JavaScript as custom HTML elements. You'll need to import the JavaScript file in your application.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'devise-webauthn'\n```\n\nAnd then execute:\n\n    $ bundle install\n\nOr install it yourself as:\n\n    $ gem install devise-webauthn\n\n## Usage\n\nFirst, ensure you have Devise set up in your Rails application. For a full guide on setting up Devise, refer to the [Devise documentation](https://github.com/heartcombo/devise?tab=readme-ov-file#getting-started).\nThen, follow these steps to integrate Devise::Webauthn:\n1. **Run Devise::Webauthn Generator:**\n   Run the generator to set up necessary configurations and migrations:\n   ```bash\n   $ bin/rails generate devise:webauthn:install\n   ```\n\n   You can optionally specify a different resource name (defaults to \"user\"):\n   ```bash\n   $ bin/rails generate devise:webauthn:install --resource-name=RESOURCE_NAME\n   ```\n\n   The generator will:\n    - Create the WebAuthn initializer (`config/initializers/webauthn.rb`)\n    - Generate the `WebauthnCredential` model and migration\n    - Add `webauthn_id` field to your devise model (e.g., `User`)\n    - Configure JavaScript loading for your application (see [JavaScript Setup](#javascript-setup))\n\n2. **Run Migrations:**\n   After running the generator, execute the migrations to update your database schema:\n   ```bash\n   $ bin/rails db:migrate\n   ```\n\n3. **Update Your Devise Model:**\n   Add `:passkey_authenticatable` to your Devise model (e.g., `User`) for passkeys authentication and `:webauthn_two_factor_authenticatable` for WebAuthn-based 2FA if desired. For example:\n   ```ruby\n   class User \u003c ApplicationRecord\n     devise :database_authenticatable, :registerable,\n            :recoverable, :rememberable, :validatable,\n            :passkey_authenticatable, :webauthn_two_factor_authenticatable\n   end\n   ```\n\n4. **Configure WebAuthn Settings:**\n   Update the generated initializer file `config/initializers/webauthn.rb` with your application's specific settings, such as `rp_name`, and `allowed_origins`. For example:\n   ```ruby\n    WebAuthn.configure do |config|\n      # This value needs to match `window.location.origin` evaluated by\n      # the User Agent during registration and authentication ceremonies.\n      config.allowed_origins = [\"https://yourapp.com\"]\n\n      # Relying Party name for display purposes\n      config.rp_name = \"Your App Name\"\n    end\n    ```\n\u003e [!TIP]\n\u003e You can find a working example on how to use this gem for passwordless and two factor authentication in [`devise-webauthn-rails-demo`](https://github.com/cedarcode/devise-webauthn-demo-app).\n\n5. **Include bundled WebAuthn JavaScript in your application:**\n   The install generator automatically configures JavaScript loading based on your setup:\n\n   **For importmap-rails:**\n   - Adds `pin \"devise/webauthn\", to: \"devise/webauthn.js\"` to `config/importmap.rb`\n   - Adds `import \"devise/webauthn\"` to `app/javascript/application.js`\n\n   **For node setups (esbuild, Bun, etc.):**\n   - Adds `\u003c%= javascript_include_tag \"devise/webauthn\" %\u003e` to your application layout\n\n   If the automatic setup doesn't work for your configuration, you can manually include the JavaScript:\n   ```erb\n   \u003c%= javascript_include_tag \"devise/webauthn\" %\u003e\n   ```\n\n#### Behavior\n\nWhen the form is submitted:\n1. The default form submission is prevented\n2. The browser's WebAuthn prompt is triggered with the provided options\n3. Upon successful authentication, the credential response is stored in the hidden input\n4. The form is submitted with the credential data\n\n## How It Works\n\n### Passkey authentication\n\n#### Adding Passkeys\nSigned-in users can add passkeys by visiting `/users/passkeys/new`.\n\n#### Sign In with Passkeys\nWhen a user visits `/users/sign_in` they can choose to authenticate using a passkey. The authentication flow is handled by `PasskeysAuthenticatable` strategy.\n\nThe WebAuthn passkey sign-in flow works as follows:\n1. User clicks \"Sign in with Passkey\", starting a WebAuthn authentication ceremony.\n2. Browser shows available passkeys.\n3. User selects a passkey and verifies with their [authenticator](https://www.w3.org/TR/webauthn-3/#webauthn-authenticator).\n4. The server verifies the response and signs in the user.\n\n### Two-Factor Authentication (2FA) with WebAuthn\n\n#### Adding Security Keys for 2FA\nSigned-in users can add security keys by visiting `/users/second_factor_webauthn_credentials/new`.\n\n#### 2FA Sign In with Security Keys\nWhen a user that has 2FA enabled (i.e., has registered passkeys or security keys) visits `/users/sign_in`, after entering their primary credentials (e.g., email and password), they will be prompted to complete the second factor authentication using WebAuthn. The authentication flow is handled by `WebauthnTwoFactorAuthenticatable` strategy.\n\nThe two factor authentication flow with WebAuthn works as follows:\n1. User enters their primary credentials (e.g., email and password) and submits the form.\n2. If the user has 2FA enabled, they are redirected to a second factor authentication page.\n3. User clicks \"Use security key\", starting a WebAuthn authentication ceremony.\n4. Browser shows available credentials (which can be both passkeys and security keys).\n5. User selects a credential and verifies with their [authenticator](https://www.w3.org/TR/webauthn-3/#webauthn-authenticator).\n6. The server verifies the response and signs in the user.\n\n## Customization\n\n### Customizing Views\nSimilar to [views customization on Devise](https://github.com/heartcombo/devise?tab=readme-ov-file#configuring-views), to customize the views, you can copy the view files from the gem into your application. Run the following command:\n```bash\n$ bin/rails generate devise:webauthn:views\n```\n\nIf you want to customize only specific views, you can copy them individually. For example, to copy only the passkeys views:\n```bash\n$ bin/rails generate devise:webauthn:views -v passkeys\n```\n\n### Helper methods\nDevise::Webauthn provides helpers that can be used in your views. These helpers accept either a resource name (e.g., `:user`) or a resource object (e.g., `@user`) as the first argument.\n\nFor example, for a resource named `user`, you can use the following helpers:\n\nTo add a form for logging in with passkeys:\n```erb\n\u003c%= login_with_passkey_form_for(:user) do |form| %\u003e\n  \u003c%= form.submit \"Log in with passkeys\" %\u003e\n\u003c% end %\u003e\n```\n\nTo add a form for logging in with security keys (2FA):\n```erb\n\u003c%= login_with_security_key_form_for(@resource) do |form| %\u003e\n  \u003c%= form.submit \"Use security key\" %\u003e\n\u003c% end %\u003e\n```\n\nTo add a passkeys creation form:\n```erb\n\u003c%= passkey_creation_form_for(:user) do |form| %\u003e\n  \u003c%= form.label :name, 'Passkey name' %\u003e\n  \u003c%= form.text_field :name, required: true %\u003e\n  \u003c%= form.submit 'Create Passkey' %\u003e\n\u003c% end %\u003e\n```\n\n### Handling unsupported WebAuthn\n\nThe custom elements check for WebAuthn API support when they connect to the DOM. If the browser doesn't support WebAuthn, a `webauthn:unsupported` event is dispatched and the form submission handler is not attached.\n\n```javascript\ndocument.addEventListener('webauthn:unsupported', (event) =\u003e {\n  const { action } = event.detail; // 'create' or 'get'\n\n  // Hide the WebAuthn form and show a message\n  hideWebauthnFormWithMessage('Your browser does not support WebAuthn');\n});\n```\n\n### Customizing Javascript Error Handling\n\nBy default, WebAuthn errors during registration or authentication are displayed using the browser's `alert()` dialog. You can customize this behavior by listening to the `webauthn:prompt:error` event.\n\n#### Listening for WebAuthn Errors\n\nThe custom elements dispatch a `webauthn:prompt:error` event whenever an error occurs during the WebAuthn prompt interaction (registration or authentication). You can listen for this event and provide custom error handling:\n\n```javascript\ndocument.addEventListener('webauthn:prompt:error', (event) =\u003e {\n  event.preventDefault(); // Prevent the default alert\n\n  const { error, action } = event.detail;\n\n  // Your custom error handling\n  console.error(`WebAuthn ${action} failed:`, error);\n  showFlashMessage(error.message, 'error');\n});\n```\n\n#### Event Details\n\nThe event includes the following information in `event.detail`:\n- `error`: The error object thrown during the WebAuthn operation\n- `action`: Either `\"create\"` (for registration) or `\"get\"` (for authentication)\n\n#### Handling Specific Error Types\n\nWebAuthn operations can fail for various reasons. Here are some common error types you might want to handle:\n\n```javascript\ndocument.addEventListener('webauthn:prompt:error', (event) =\u003e {\n  event.preventDefault();\n\n  const { error, action } = event.detail;\n\n  switch (error.name) {\n    case 'NotAllowedError':\n      // User cancelled the operation or timeout\n      showFlashMessage('Operation cancelled or timed out', 'warning');\n      break;\n\n    default:\n      // Generic error message\n      showFlashMessage(`Authentication error: ${error.message}`, 'error');\n  }\n});\n```\n\n#### Different Handling for Registration vs Authentication\n\nYou can provide different error handling based on whether the error occurred during registration or authentication:\n\n```javascript\ndocument.addEventListener('webauthn:prompt:error', (event) =\u003e {\n  event.preventDefault();\n\n  const { error, action } = event.detail;\n\n  if (action === 'create') {\n    // Handle registration errors\n    handleRegistrationError(error);\n  } else if (action === 'get') {\n    // Handle authentication errors\n    handleAuthenticationError(error);\n  }\n});\n```\n\n**Note:** If you don't call `event.preventDefault()`, the default `alert()` will still be shown.\n\n### Customizing Controllers\nSimilar to [controllers customization on Devise](https://github.com/heartcombo/devise?tab=readme-ov-file#configuring-controllers), you can customize the Devise::Webauthn controllers.\n\n1. Create your custom controllers using the generator which requires a scope:\n```bash\n$ bin/rails generate devise:webauthn:controllers [scope]\n```\n\n2. Tell the router to use your custom controllers. For example, if your scope is `users`:\n```ruby\ndevise_for :users, controllers: {\n  passkeys: 'users/passkeys'\n}\n```\n\n3. Change or extend the generated controllers as needed.\n\n### Manually implementing WebAuthn forms\n\nThe gem provides two custom HTML elements for WebAuthn operations. While the [form helpers](#helper-methods) handle this automatically, you can use these elements directly for custom implementations.\n\n#### `\u003cwebauthn-create\u003e`\n\nUsed for registering new credentials (passkeys or security keys).\n\n```html\n\u003cform action=\"/passkeys\" method=\"post\"\u003e\n  \u003cwebauthn-create data-options-json=\"\u003c%= create_passkey_options(@user).to_json %\u003e\"\u003e\n    \u003cinput type=\"hidden\" name=\"public_key_credential\" data-webauthn-target=\"response\"\u003e\n    \u003cinput type=\"text\" name=\"name\" placeholder=\"Passkey name\"\u003e\n    \u003cbutton type=\"submit\"\u003eCreate Passkey\u003c/button\u003e\n  \u003c/webauthn-create\u003e\n\u003c/form\u003e\n```\n\n**Requirements:**\n- Must be wrapped in a `\u003cform\u003e` element\n  - The form's action should point to the appropriate endpoint – you can use the provided url helpers:\n    - For creating passkeys: `passkeys_path(resource_name)`\n    - For creating 2FA security keys: `second_factor_webauthn_credentials_path(resource_name)`\n- Requires a `data-options-json` attribute containing JSON-serialized WebAuthn creation options\n- Must contain a hidden input with `data-webauthn-target=\"response\"` to store the credential response\n- Must contain the submit button — the element intercepts form submission, calls the WebAuthn API, stores the credential in the hidden input, and then re-submits the form\n\n#### `\u003cwebauthn-get\u003e`\n\nUsed for authenticating with existing credentials.\n\n```html\n\u003cform action=\"/users/sign_in\" method=\"post\"\u003e\n  \u003cwebauthn-get data-options-json=\"\u003c%= passkey_authentication_options.to_json %\u003e\"\u003e\n    \u003cinput type=\"hidden\" name=\"public_key_credential\" data-webauthn-target=\"response\"\u003e\n    \u003cbutton type=\"submit\"\u003eSign in with Passkey\u003c/button\u003e\n  \u003c/webauthn-get\u003e\n\u003c/form\u003e\n```\n\n**Requirements:**\n- Must be wrapped in a `\u003cform\u003e` element\n    - The form's action should point to the appropriate endpoint – you can use the provided url helpers:\n        - For passkey sign-in: `session_path(resource_name)`\n        - For 2FA with WebAuthn: `two_factor_authentication_path(resource_name)`\n- Requires a `data-options-json` attribute containing JSON-serialized WebAuthn request options\n- Must contain a hidden input with `data-webauthn-target=\"response\"` to store the credential response\n- Must contain the submit button — the element intercepts form submission, calls the WebAuthn API, stores the credential in the hidden input, and then re-submits the form\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests.\nTo run the linter, use `bundle exec rubocop`.\n\nBefore submitting a pull request, ensure that tests and linter pass.\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/cedarcode/devise-webauthn.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcedarcode%2Fdevise-webauthn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcedarcode%2Fdevise-webauthn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcedarcode%2Fdevise-webauthn/lists"}