Add "Login with Passkeys" to your React.js app in < 2 mins
Tags: webdev, javascript, react, authjs
Published: 2024-04-03 15:06:10

Passkeys, passkeys, passkeys! Everyone's talking about them. With [Amazon](https://www.theverge.com/2023/10/23/23928589/amazon-passkey-support-web-ios-shopping-mobile-app?ref=pangea.cloud) rolling out passkeys last year and [Google](https://blog.google/technology/safety-security/passkeys-default-google-accounts/?ref=pangea.cloud) 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](https://pangea.cloud/securebydesign/authn-using-passkeys/) 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
```bash
npx create-react-app passkeys-demo && \
cd passkeys-demo && \
npm i @pangeacyber/react-auth
```

### Step 2: Create an account on [pangea.cloud](https://pangea.cloud/?utm_source=devto&utm_medium=passkeys-reactjs-blog)
Head over to [pangea.cloud](https://pangea.cloud/?utm_source=devto&utm_medium=passkeys-reactjs-blog) 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:
```env
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:
```js
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:
```js
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/](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:

{% embed https://www.youtube.com/watch?v=M2kPx1WteEE %}

Let's test it out!

{% embed https://www.youtube.com/watch?v=2jSHLlMpBiQ %}