heritageholdings / passkey-example

An example repository showcasing end-to-end passkey registration and authentication on a mobile app using Node.js and React Native
MIT License
15 stars 2 forks source link
effect-ts nodejs passkey passkeys-demo passwordless react-native simplewebauthn webauthn

React Native and Node.js Passwordless Authentication with Passkey

This is an example repository showcasing end-to-end passkey registration and authentication on a mobile app. It uses Node.js with SimpleWebAuthn and React Native with react-native-passkey. For more information about the implementation, architecture, and technologies used, please refer to the related articles:

  1. Passwordless Authentication With Passkey: How It Works and Why It Matters
  2. How to Implement Passwordless Authentication with Passkey using React Native and Node.js - Part 1
  3. How to Implement Passwordless Authentication with Passkey using React Native and Node.js - Part 2

Please remember that this repository serves as a showcase, offering a demonstration of both backend and frontend code essential for implementing passkey authentication. It is important to note that certain simplifications have been incorporated into the code to enhance readability and understanding and is not intended for production use as would be needed to adapt and enhance the code for production environments according to best practices and security standards.

Prerequisites

in addition to these, this repository provides a practical demonstration leveraging Ngrok to acquire a complimentary static subdomain and expose your local server to the internet, in order to simplify the configuration required by the Apple associated domains. For step-by-step guidance on installation, please visit the Ngrok website. Once the installation and registration processes are completed, users can easily procure a free static endpoint through the Ngrok dashboard under Cloud Edge > Endpoints.

Setup

Variable Description
WEBAUTHN_RPID The Relying Party ID (RP ID) is a unique identifier for the Relying Party entity, which is the application that is using WebAuthn to authenticate users. Insert here the Ngrok free static subdomain.
WEBAUTHN_RPORIGIN The origin of the Relying Party, automatically valued via WEBAUTHN_RPID.
WEBAUTHN_RPNAME The name of the Relying Party, you can use whatever name you prefer.
WEBAUTHN_ANDROID_CERT_FINGERPRINTS The SHA-256 hashes of the Android key pairs used to sign the app. You can obtain this running keytool -list -v -keystore app/debug.keystore, pointing to the app keystore.
WEBAUTHN_IOS_TEAM_ID The Team ID of the Apple Developer account used to sign the app.

Repository organization

The mono-repo is organized following the nx monorepo structure, with the following main folders:

How to run

If you have followed the setup steps, you should have the backend server running on your local machine and the mobile app running on your device/emulator. The mobile app will allow you to register a new credential, inserting an email and pressing the Register button. If everything is configured correctly, the new passkey registration ceremony should begin and the user is prompted to register a new passkey by authenticating via biometric

Login / Registration Passkey Registration Passkey Registration with Face ID

If the passkey registration is successful, the user is directed to the home screen, where the user will be able to see his email, the IDs of the authenticators registered by him (and a panda holding a bamboo passkey!). From here you can log out to test logging in with the passkey you just registered

Once you return to the first authentication screen, you can press "Login". At this point the authentication ceremony will begin which will allow you to re-access the application using the previously registered passkey.

If any error occurs during execution, registration or authentication, check the logs of either the mobile app or the backend.

Please remember that in this simple demo, the backend server is not persistent, so if you restart it, all the registered credentials will be lost!