logo
Menu
Add "Login with Passkeys" to your AWS Amplify app in <5 mins

Add "Login with Passkeys" to your AWS Amplify app in <5 mins

Passkey auth is a more popular and secure auth method. In this tutorial, you will learn how to add Passkeys to you web app on AWS Amplify with Pangea AuthN.

Published Apr 30, 2024
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.

What is AWS Amplify?

AWS Amplify is a service that lets you host backends such as databases, storage, etc for your web and mobile applications without manually configuring resources or interfaces between different AWS resources.
In this tutorial, we will build a “Login with Passkeys” authentication using Pangea AuthN and use AWS amplify to perform authenticated CRUD operations on our Amplify backend GraphQL APIs. Thus demonstrating how to add passkeys in 1-click while retaining secure app functions such as our CRUD operations.

How do I build passkeys in my Next.js app?

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 Next.js app and implement passkeys in just a few steps.

Step 1: Clone Next.js Demo App and Install Pangea AuthN react wrapper

1
2
3
git clone https://github.com/pangeacyber/pangea-authn-amplify-backend-demo.git && \
cd pangea-authn-amplify-backend-demo && \
npm i @pangeacyber/react-auth pangea-node-sdk

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:
1
2
3
4
5
6
7
8
NEXT_PUBLIC_AUTHN_HOSTED_LOGIN_URL="<PANGEA_AUTH_LOGIN_URL>"
NEXT_PUBLIC_AUTHN_CLIENT_TOKEN="<PANGEA_AUTH_CLIENT_TOKEN>"
# Update if you choose something outside AWS US cluster
NEXT_PUBLIC_PANGEA_DOMAIN=aws.us.pangea.cloud

PANGEA_TOKEN="<PANGEA_TOKEN>"
# Update if you choose something outside AWS US cluster
PANGEA_DOMAIN=aws.us.pangea.cloud

Step 3: Understand how Pangea AuthN works in the Next.js app

In the _app.tsx file with the <AuthProvider> component that maintains authentication context and state across the application.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import "@/styles/globals.css";
import type { AppProps } from "next/app";
import { AuthProvider } from "@pangeacyber/react-auth";

export default function App({ Component, pageProps }: AppProps) {
const hostedLoginURL = process?.env?.NEXT_PUBLIC_AUTHN_HOSTED_LOGIN_URL || "";
const authConfig = {
clientToken: process?.env?.NEXT_PUBLIC_AUTHN_CLIENT_TOKEN || "",
domain: process?.env?.NEXT_PUBLIC_PANGEA_DOMAIN || "",
};

return (
<AuthProvider loginUrl={hostedLoginURL} redirectPathname="/authenticated" config={authConfig}>
<Component {...pageProps} />
</AuthProvider>

);
}
Now that the AuthProvider keeps context across the application, we can see the login and logout functionality implemented using the useAuth hook in our src/pages/index.tsx file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { MainComponent } from "@/components/main-component";
import { useAuth } from "@pangeacyber/react-auth";
import { useRouter } from "next/router";
import { useEffect } from "react";

export default function Home() {
const router = useRouter();
const { authenticated, user, loading, login } = useAuth();

useEffect(() => {
// Check if user authenticated
if(!loading && authenticated) {
router.push("/authenticated");
}
}, [loading, user, authenticated])

return (
<MainComponent login={login} />
);
}

Step 3: Enable Passkeys Authentication in Pangea console

Since we’re using Next.js, we need to add an authorized redirect, so that Pangea’s AuthN hosted pages can successfully redirect us back to the http://localhost:3000/authenticated (which is our default login success route in this app) when a user is done authenticating.
So first, let’s go under General > Redirect (Callback) Settings and add http://localhost:3000/authenticated 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:
Once we test the login and it works successfully, we will get redirected to http://localhost:3000/authenticated. Here, you will find a form that asks you for your favorite ice cream flavor.
Screenshot of Authenticated Page with form
http://localhost:3000/authenticated
Let’s set up the backend database to make the form work!

Step 4: Setup Amplify data backend

Amplify makes it super easy to set up the DynamoDB for a specific GraphQL schema file and its associated GraphQL server all in just one command. Run
1
2
amplify init
amplify push -y
Once it pushes the schema successfully to your Amplify backend, you should see the GraphQL endpoint and the GraphQL API key in the terminal output. Update your .env.example with the remaining AWS Amplify credentials:
1
2
3
4
5
AWS_REGION="<AWS_REGION>"
AWS_APPSYNC_GRAPHQL_ENDPOINT="<AWS_APPSYNC_GRAPHQL_ENDPOINT>"
AWS_APPSYNC_REGION="<AWS_REGION>"
AWS_APPSYNC_AUTHENTICATION_TYPE="<AUTH_TYPE>"
AWS_APPSYNC_API_KEY="<AWS_APPSYNC_API_KEY>"

Step 5: Enabling API Authentication for Secure Data Fetching

To prevent malicious users from performing CRUD operations on our Amplify backend databases, we need to be able to validate the user’s authenticated session. We will use middleware to authenticate the request before accessing our sensitive APIs.
Head over to src/pages/api/send-data.ts and notice that the last exports the API handler with the withAPIAuthentication middleware.
The withAPIAuthentication middleware is consequently implemented in src/utils/authCheck with a few handy little functions to verify the user's identity based on their session token.
Thus, without any extra code, we can easily ensure that ONLY authenticated users can submit their favorite ice cream flavor 🍨!
 

Comments