Back to Blog

Add "Login with Passkeys" to your React.js app in < 2 mins

Pranav Shikarpur
Pranav Shikarpur

Passkeys, passkeys, passkeys! Everyone's talking about them. With Amazon rolling out passkeys last year and Google encouraging users to make them the default authentication method, it raises the question: How do I add them to my app?

How do passkeys work?

If you’re just interested in implementing them, you can skip this section. No offense taken 😉

FIDO2 multidevice credentials more often referred to as “passkeys” is a standard introduced by the FIDO alliance. It’s an extremely powerful way of using public-key cryptography to verify the identity of a user without passwords, multi-factor, etc. The public / private key pair is usually generated and securely stored on a hardware or software authenticator device.

To learn more about how passkeys and authenticators work in detail, check out the Secure By Design Hub article on passkeys.

How do I build it in?

In this tutorial, we’re going to leverage Pangea AuthN’s hosted pages to be able to quickly configure passkeys without building all the cryptographic mayhem from scratch 😅. To prove that it’s easy to add passkeys into any application in just a few minutes, I’m going to start with a fresh new React.js app and implement passkeys in just a few steps.

Step 1: Create a new React App and install Pangea AuthN react wrapper

npx create-react-app passkeys-demo && \
cd passkeys-demo && \
npm i @pangeacyber/react-auth

Step 2: Create an account on pangea.cloud

Head over to pangea.cloud and create an account for free. Then in the developer console, enable the “AuthN” service and grab the following tokens. These tokens will be pasted in your .env config file as shown below.

Add these tokens into a .env file like this:

REACT_APP_LOGIN_URL="<PROJECT_HOSTED_LOGIN_URL>"
REACT_APP_CLIENT_TOKEN="<PROJECT_CLIENT_TOKEN>"
REACT_APP_PANGEA_DOMAIN="<PANGEA_DOMAIN>"

Step 3: Add the Pangea React Auth components to the new React app

Now we edit our index.js file with the <AuthProvider> component that maintains authentication context and state across the application.

So our index.js file should look like this:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

// Import Pangea AuthProvider component
import {AuthProvider} from '@pangeacyber/react-auth';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    {/* We wrap the App component with our AuthProvider */}
    <AuthProvider
      config={{
        domain: process.env.REACT_APP_PANGEA_DOMAIN,
        clientToken: process.env.REACT_APP_CLIENT_TOKEN,
        useJwt: false
      }}
      cookieOptions={{
        useCookie: true,
        cookieName: "pangea-authn"
      }}
      loginUrl={process.env.REACT_APP_LOGIN_URL}
      useStrictStateCheck={false}
    >
      <App />
    </AuthProvider>
  </React.StrictMode>
);

Now that we have the AuthProvider keeping context across the application, we can now implement the login and logout functionality by simply calling the useAuth hook in our App.js file.

Thus your App.js file should look like this:

import './App.css';

// Pangea AuthN imports
import { useAuth } from "@pangeacyber/react-auth";

function App() {
  const { authenticated, user, login, logout } = useAuth();

  return (
      <div className="App">
        <header className="App-header">
          <h1 >Login with Passkeys 🔑</h1>
          <p>
     {/* Check if user is authenticated */}
            { authenticated ?
              <p>
                Welcome, {user.email}!
                <br />
                <button style={{ 
                  background: 'linear-gradient(to right, #ff416c, #ff4b2b)',
                  border: 'none',
                  color: 'white',
                  padding: '10px 20px',
                  borderRadius: '5px',
                  cursor: 'pointer',
                  fontSize: '16px',
                  fontWeight: 'bold',
                  boxShadow: '0px 2px 5px rgba(0, 0, 0, 0.2)',
                }} 
                onClick={logout}>Logout</button>
              </p>
              :
            <button style={{ 
              background: 'linear-gradient(to right, #416cff, #4b2bff)',
              border: 'none',
              color: 'white',
              padding: '10px 20px',
              borderRadius: '5px',
              cursor: 'pointer',
              fontSize: '16px',
              fontWeight: 'bold',
              boxShadow: '0px 2px 5px rgba(0, 0, 0, 0.2)',
            }}
            onClick={login}>Login</button>
          }
          </p>
          <a
            className="App-link"
            href="https://pangea.cloud/services/authn/?utm_source=blog&utm_medium=passkeys-snippet"
            target="_blank"
            rel="noopener noreferrer"
          >
            Try Pangea AuthN for free today!
          </a>
        </header>
      </div>
  );
}

export default App;

Step 4: Enable Passkeys Authentication in Pangea console

Since we’re using a React SPA (single page application), we need to add an authorized redirect, so that Pangea’s AuthN hosted pages can successfully redirect us back to the http://localhost:3000/ when a user is done authenticating.

So first, let’s go under General > Redirect (Callback) Settings and add http://localhost:3000/ as a redirect and save it.

Here comes the last step, let’s enable Passkeys! Head over to Single Sign On > Passkeys and enable it. Optionally you can choose to enable fallback authentication options based on your desired user experience.

Here’s a quick video on how you can enable it in settings:

Let's test it out!

Get updates in your inbox and subscribe to our newsletter

background landmass