Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds Webauthn support (TouchID, FaceID) to dbAuth #5680

Merged
merged 72 commits into from
Jul 18, 2022
Merged

Adds Webauthn support (TouchID, FaceID) to dbAuth #5680

merged 72 commits into from
Jul 18, 2022

Conversation

cannikin
Copy link
Member

@cannikin cannikin commented Jun 1, 2022

Did you know you can enable TouchID, FaceID, Yubikey support (and more) in the browser?? I didn’t, until I signed in to Ebay the other day and it asked me if I wanted to use TouchID for future logins. Blew my mind. Apparently this has been a possibility since around 2020, but I’d never seen a site use it until now.

I haven't seen any of our other auth providers supporting Webauthn yet, so this could be a unique advantage to dbAuth. Here's a list of supported browser and devices:

image

Registration

The first time Webauthn is enabled for a user (called "Registration") the flow looks like:

  1. User logs into the site using username/password like normal
  2. If the browser sees that Webauthn is supported, asks the user if they want to use TouchID/FaceID going forward (if no support, just logged into the site like normal)
  3. If they say yes, they are prompted to authenticate (fingerprint or face). This data is sent to the server and a unique ID credentialID and credentialPublicKey are saved for this single device
  4. The server creates a cookie that says "this person used webauthn to authenticate" (now we know we can show a TouchID/FaceID prompt the next time they return to the site)
  5. User is logged into the site like normal

Authentication

On subsequent logins (called "Authentication") the flow goes:

  1. Browser sees that user has the "webauthn enabled" cookie, so shows the "Use TouchID/FaceID to login" instead of the default username/password (user can still choose to use username/password instead, if they want)
  2. Webauthn response is sent up to the server and checked against the database to see if the provided credentialID exists for a user, and that a valid signature is returned
  3. If found, user is logged in, if not then an error is returned

Note that a credentialID is unique to a device, so if you enable TouchID on your laptop, it won't automatically work on your phone: you'd need to start from step 1 of Registration again when you go to a new device. But then going forward you could log into either site.

Database

We will need to store some extra data in the database going forward:

  • A webauthnChallenge field on the user, which is a unique string that's generated when a Webauthn request starts. The response from the browser will contain this same string. Putting this on the user table means that only a single device can be in the middle of a Registration/Authentication flow at a time, which seems like a reasonable limitation. This means that you can't start the Registration process on your desktop, then before using your fingerprint start the Registration on your phone, complete the Registration on your phone, then come back to your desktop and scan your fingerprint—the webauthnChallenge will be wiped out by the phone's Registration flow.
  • A new table UserCredential containing all of the devices/credentials that are associated with a single user. This is a one-to-many relationship (a User has many UserCredentials).

Release Notes

You can now let your users use their face, fingerprint or a PIN to log in with dbAuth! WebAuthn has been a browser standard since 2020 and it provides a unified interface to TouchID, FaceID, Windows Hello, as well as third party devices like Yubikey.

  • If you don't want to enable WebAuthn then it's just business as usual with your app, nothing needs to change!
  • If you do want to enable, check out the extensive docs the dbAuth doc page. You'll need to make a few changes:
    • Add a new model and an additional field in your User model
    • Add configuration to api/src/functions/auth.js
    • Re-generate your login page, or add custom logic to show the WebAuthn prompts

@netlify
Copy link

netlify bot commented Jun 1, 2022

Deploy Preview for redwoodjs-docs ready!

Name Link
🔨 Latest commit 9262c6a
🔍 Latest deploy log https://app.netlify.com/sites/redwoodjs-docs/deploys/62d576ae263f0d0008903766
😎 Deploy Preview https://deploy-preview-5680--redwoodjs-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

@cannikin cannikin self-assigned this Jun 1, 2022
@cannikin cannikin added topic/auth release:feature This PR introduces a new feature labels Jun 1, 2022
@cannikin cannikin changed the title Adds Webauthn support to dbAuth Adds Webauthn support (TouchID, FaceID) to dbAuth Jun 2, 2022
Error when importing ESM modules more than one level deep: MasterKale/SimpleWebAuthn#168
This prevents an annoying UX case where you removed the `webAuthn` cookie—you are sent into the registration flow but can’t register because your devices is already in the DB, so you’re asked to authenticate, which means you have to scan your fingerprint/face again
This makes it so that if someone tampers with the cookie, or their credential has been removed from the database, their webAuthn cookie is removed and sent back to the username/password flow
@cannikin cannikin merged commit 2cb1226 into main Jul 18, 2022
@cannikin cannikin deleted the rc-webauthn branch July 18, 2022 15:51
@redwoodjs-bot redwoodjs-bot bot added this to the next-release milestone Jul 18, 2022
@cannikin
Copy link
Member Author

MERGEDDDDD Sorry about the conflicts on the strict PR @dac09 😬

@dac09
Copy link
Collaborator

dac09 commented Jul 18, 2022

No worries @cannikin - but I think we need to ✋ HODL shipping this - I'm getting errors rebuilding the test project fixture. (Module base64url not found).

@cannikin
Copy link
Member Author

Hmm base64url is added to the package.json in either api or auth…maybe I missed one?

@cannikin
Copy link
Member Author

Double checked and base64url is a dependency of the api package, and any reference to base64url in the code is in DbAuthHandler, which is in api.

Maybe we should do that thing where it actually installs as a dependency in the app itself if you use dbAuth? Although it's a pretty tiny package, the raw TS source is only 50 lines of code...

@dac09
Copy link
Collaborator

dac09 commented Jul 21, 2022

@cannikin - I can confirm the failure is happening because of this PR - why...? I don't really know.

To see it, just run yarn build:test-project --rebuild-fixture

Without this PR: ✅ all good (you can use the branch try/revert-webauthn)
With this PR: 👎fails with the message above when trying to generate the homepage.

What do you say we revert till we find the solution?


Update: there seems to be two problems - the one above and.... the setup and generate dbAuth commands now prompt - so the testproject generator gets stuck. Is there a flag we could pass it to skip the prompt? yarn rw setup auth dbAuth --help doesn't give me any info.

Would it be possible to move the prompt to inside the dbAuth setup command? It sets a bad precedent, because what if providerX comes along and wants to have a couple different variants? See the setup ui command for reference, where we get both the help for the specific ui library, as well as code grouped into the library specific file rather than the "global" setup ui command.

@dac09 dac09 mentioned this pull request Jul 21, 2022
17 tasks
dac09 added a commit to dac09/redwood that referenced this pull request Jul 22, 2022
…o feat/ts-strictmode-gen

* 'feat/ts-strictmode-gen' of github.com:dac09/redwood: (94 commits)
  fix(deps): update dependency @graphql-codegen/cli to v2.9.1 (redwoodjs#6013)
  Little grammar change (redwoodjs#6006)
  chore: connect repo to nx cloud to speed up builds (redwoodjs#5988)
  fix(deps): update dependency @testing-library/user-event to v14.3.0 (redwoodjs#6004)
  fix(deps): update graphqlcodegenerator monorepo (redwoodjs#6005)
  chore(deps): update dependency @auth0/auth0-spa-js to v1.22.2 (redwoodjs#6003)
  fix(graphql): Fixes multiValueHeader handling (and CORS) in graphql handler  (redwoodjs#5970)
  chore(deps): update dependency @nhost/hasura-auth-js to v1.4.0 (redwoodjs#6001)
  chore(deps): update dependency @nhost/nhost-js to v1.4.7 (redwoodjs#5999)
  fix(deps): update dependency cross-undici-fetch to v0.4.14 (redwoodjs#6000)
  chore(deps): update dependency @azure/msal-browser to v2.28.0 (redwoodjs#5994)
  fix(deps): update dependency concurrently to v7.3.0 (redwoodjs#5995)
  chore(deps): update dependency @simplewebauthn/browser to v5.3.0 (redwoodjs#5989)
  chore(deps): update dependency @simplewebauthn/server to v5.3.0 (redwoodjs#5990)
  chore(deps): update dependency @simplewebauthn/typescript-types to v5.3.0 (redwoodjs#5991)
  fix(deps): update dependency @testing-library/user-event to v14.2.6 (redwoodjs#5992)
  fix(deps): update typescript-eslint monorepo to v5.30.7 (redwoodjs#5993)
  chore: clean up mock auth client (redwoodjs#5911)
  Adds Webauthn support (TouchID, FaceID) to dbAuth (redwoodjs#5680)
  chore(deps): update dependency octokit to v2.0.4 (redwoodjs#5986)
  ...
@jtoar jtoar modified the milestones: next-release, v2.2.0 Jul 22, 2022
jtoar added a commit that referenced this pull request Aug 6, 2022
jtoar added a commit that referenced this pull request Aug 9, 2022
* remove clerk codemod

see #5969

* revert 4880 (fix clerk)

see #4880

* changes for okta

see #5088

* changes for webauthn

see #5680
@jtoar jtoar modified the milestones: next-release, v3.0.0 Sep 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release:feature This PR introduces a new feature topic/auth
Projects
Status: Archived
Development

Successfully merging this pull request may close these issues.

3 participants