{"id":28076789,"url":"https://github.com/jaredhanson/passport-webauthn","last_synced_at":"2025-08-28T12:12:19.620Z","repository":{"id":53298795,"uuid":"196743232","full_name":"jaredhanson/passport-webauthn","owner":"jaredhanson","description":"WebAuthn authentication strategy for Passport.","archived":false,"fork":false,"pushed_at":"2024-07-05T18:00:06.000Z","size":79,"stargazers_count":49,"open_issues_count":11,"forks_count":16,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-20T04:06:45.415Z","etag":null,"topics":["fido","fido2","passkey","passport","passwordless","webauthn"],"latest_commit_sha":null,"homepage":"https://www.passportjs.org/packages/passport-fido2-webauthn/?utm_source=github\u0026utm_medium=referral\u0026utm_campaign=passport-fido2-webauthn\u0026utm_content=about","language":"JavaScript","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/jaredhanson.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","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},"funding":{"github":"jaredhanson"}},"created_at":"2019-07-13T16:30:33.000Z","updated_at":"2025-05-08T06:35:05.000Z","dependencies_parsed_at":"2025-05-13T01:51:43.670Z","dependency_job_id":"3128da99-ca15-4a73-a9a7-8d3ee7245edc","html_url":"https://github.com/jaredhanson/passport-webauthn","commit_stats":{"total_commits":143,"total_committers":1,"mean_commits":143.0,"dds":0.0,"last_synced_commit":"ff6d69bf2b6aee2f693149b82c7ace5a20717676"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/jaredhanson/passport-webauthn","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaredhanson%2Fpassport-webauthn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaredhanson%2Fpassport-webauthn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaredhanson%2Fpassport-webauthn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaredhanson%2Fpassport-webauthn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jaredhanson","download_url":"https://codeload.github.com/jaredhanson/passport-webauthn/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaredhanson%2Fpassport-webauthn/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272497264,"owners_count":24944655,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-28T02:00:10.768Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["fido","fido2","passkey","passport","passwordless","webauthn"],"created_at":"2025-05-13T01:51:39.763Z","updated_at":"2025-08-28T12:12:19.598Z","avatar_url":"https://github.com/jaredhanson.png","language":"JavaScript","funding_links":["https://github.com/sponsors/jaredhanson"],"categories":[],"sub_categories":[],"readme":"# passport-fido2-webauthn\n\n[Passport](https://www.passportjs.org/) strategy for authenticating\nwith [Web Authentication](https://www.w3.org/TR/webauthn-2/).\n\nThis module lets you authenticate using WebAuthn in your Node.js applications.\nBy plugging into Passport, WebAuthn-based sign in can be easily and\nunobtrusively integrated into any application or framework that supports\n[Connect](https://github.com/senchalabs/connect#readme)-style middleware,\nincluding [Express](https://expressjs.com/).\n\n\u003cdiv align=\"center\"\u003e\n\n:heart: [Sponsors](https://www.passportjs.org/sponsors/?utm_source=github\u0026utm_medium=referral\u0026utm_campaign=passport-fido2-webauthn\u0026utm_content=nav-sponsors)\n\n\u003c/div\u003e\n\n## Install\n\n```sh\n$ npm install passport-fido2-webauthn\n```\n\n## Usage\n\nThe WebAuthn authentication strategy authenticates users using a public\nkey-based credential.  The authenticator which stores this credential is\ntypically the user's device or an external security key, either of which may be\nunlocked using a PIN or biometric.\n\nThe strategy takes a `verify` function as an argument, which accepts `id` and\n`userHandle` as arguments.  `id` identifies a public key credential that has\nbeen associated with a user's account.  `userHandle` maps the credential to a\nspecific user account.  When authenticating a user, this strategy obtains this\ninformation from a WebAuthn assertion.\n\nThe `verify` function is responsible for determining the user to which the\naccount at the OP belongs.  Once it has made a determination, it invokes `cb`\nwith the user record and a public key.  The public key is used to\ncryptographically verify the WebAuthn assertion, thus authenticating the user.\n\nThis strategy also takes a `register` function as an argument, which is called\nwhen registering a new credential, and accepts `user`, `id` and `publicKey` as\narguments.  `user` represents a specific user account with which to associate\nthe credential.  `id` identifies the public key credential.  `publicKey` is the\nPEM-encoded public key.\n\nThe `register` function is responsible for associating the new credential with\nthe account.  Once complete, it invokes `cb` with the user record.\n\nBecause the `verify` and `register` functions are supplied by the application,\nthe app is free to use any database of its choosing.  The example below\nillustrates usage of a SQL database.\n\n```js\nvar WebAuthnStrategy = require('passport-fido2-webauthn');\nvar SessionChallengeStore = require('passport-fido2-webauthn').SessionChallengeStore;\n\nvar store = new SessionChallengeStore();\n\npassport.use(new WebAuthnStrategy({ store: store },\n  function verify(id, userHandle, cb) {\n    db.get('SELECT * FROM public_key_credentials WHERE external_id = ?', [ id ], function(err, row) {\n      if (err) { return cb(err); }\n      if (!row) { return cb(null, false, { message: 'Invalid key. '}); }\n      var publicKey = row.public_key;\n      db.get('SELECT * FROM users WHERE rowid = ?', [ row.user_id ], function(err, row) {\n        if (err) { return cb(err); }\n        if (!row) { return cb(null, false, { message: 'Invalid key. '}); }\n        if (Buffer.compare(row.handle, userHandle) != 0) {\n          return cb(null, false, { message: 'Invalid key. '});\n        }\n        return cb(null, row, publicKey);\n      });\n    });\n  },\n  function register(user, id, publicKey, cb) {\n    db.run('INSERT INTO users (username, name, handle) VALUES (?, ?, ?)', [\n      user.name,\n      user.displayName,\n      user.id\n    ], function(err) {\n      if (err) { return cb(err); }\n      var newUser = {\n        id: this.lastID,\n        username: user.name,\n        name: user.displayName\n      };\n      db.run('INSERT INTO public_key_credentials (user_id, external_id, public_key) VALUES (?, ?, ?)', [\n        newUser.id,\n        id,\n        publicKey\n      ], function(err) {\n        if (err) { return cb(err); }\n        return cb(null, newUser);\n      });\n    });\n  }\n));\n```\n\n#### Define Routes\n\nTwo routes are needed in order to allow users to log in with their passkey or\nsecurity key.\n\nThe first route generates a randomized challenge, saves it in the\n`ChallengeStore`, and sends it to the client-side JavaScript for it to be\nincluded in the authenticator response.  This is necessary in order to protect\nagainst replay attacks.\n\n```js\nrouter.post('/login/public-key/challenge', function(req, res, next) {\n  store.challenge(req, function(err, challenge) {\n    if (err) { return next(err); }\n    res.json({ challenge: base64url.encode(challenge) });\n  });\n});\n```\n\nThe second route authenticates the authenticator assertion and logs the user in.\n\n```js\nrouter.post('/login/public-key',\n  passport.authenticate('webauthn', { failWithError: true }),\n  function(req, res, next) {\n    res.json({ ok: true });\n  },\n  function(err, req, res, next) {\n    res.json({ ok: false });\n  });\n```\n\n## Examples\n\n* [todos-express-webauthn](https://github.com/passport/todos-express-webauthn)\n\n  Illustrates how to use the WebAuthn strategy within an Express application.\n\n## License\n\n[The MIT License](https://opensource.org/licenses/MIT)\n\nCopyright (c) 2019-2022 Jared Hanson \u003c[https://www.jaredhanson.me/](https://www.jaredhanson.me/)\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaredhanson%2Fpassport-webauthn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjaredhanson%2Fpassport-webauthn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaredhanson%2Fpassport-webauthn/lists"}