# Clerk Auth

This quick start guide will walk you through how to quickly get setup with the Passport SDK with Clerky account, register and authenticate users, and start signing messages and transactions. You can skip to the [#complete-setup](#complete-setup "mention"), and then follow the section step-by-step where each code snippet will be explained. You can also quickly pull the completed repository here  <https://github.com/0xpass/passport-clerk-quickstart> and follow along.

### Project setup

First we'll setup a Next.js project, with tailwind, we can do this with the following command, and walk through the configuration wizard, making sure to chose the app-router, and tailwind.

```bash
npx create-next-app@latest
```

### Setup and Dependencies

Firstly, we'll ensure we have all the requires dependencies. So we're going to install the Passport SDK **`@0xpass/passport`** to interact with Passport protocol, and `@clerk/nextjs` for third party authentication. We'll also install some helper packages **`@0xpass/key-signer`** to handle our signature management for delegated registration and authentication.

{% tabs %}
{% tab title="npm" %}

```bash
npm install @0xpass/passport @0xpass/key-signer @clerk/nextjs@4.2.9 viem@2.9.4
```

{% endtab %}

{% tab title="pnpm" %}

```bash
pnpm install @0xpass/passport @0xpass/key-signer @clerk/nextjs@4.2.9 viem@2.9.4
```

{% endtab %}

{% tab title="yarn" %}

```bash
yarn add @0xpass/passport @0xpass/key-signer @clerk/nextjs@4.2.9 viem@2.9.4
```

{% endtab %}
{% endtabs %}

### Environment Variables and Generating Developer Keys

In your project root, copy and paste the environment variables below.

```shellscript
NEXT_PUBLIC_SCOPE_ID=""
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=""
CLERK_SECRET_KEY=""
PRIVATE_KEY=""
```

Going one by one,

NEXT\_PUBLIC\_SCOPE\_ID can get obtained from [Configuring your scope](/authentication/configuring-your-scope.md)

You should grab your own NEXT\_PUBLIC\_CLERK\_PUBLISHABLE\_KEY, and CLERK\_SECRET\_KEY from your Clerk account.&#x20;

For Developer Key (PRIVATE\_KEY), follow [Generating DOA Keys](/appendix/generating-doa-keys.md) for generating your own keys. We'll refer to the private key generated in this step as `PRIVATE_KEY` environment variable in the example below.&#x20;

### Backend APIs

Firstly let's setup backend API for creating an account in passport protocol upon successful authentication via Clerk.&#x20;

Authentication Flow:

<figure><img src="/files/TXi7HPx2Em4wj0tfbLLC" alt=""><figcaption></figcaption></figure>

Signing Flow:

<figure><img src="/files/gEkTlSBjb5lsX0Zs5bKG" alt=""><figcaption></figcaption></figure>

This is not a part of backend, but you need a page that takes the callback from clerk, and redirects to /api/user-callback. In `app/auth/callback` we'll have the following snippet so that frontend calls the backend endpoint with user id and email address upon successful sign-in.

```typescript
"use client";
import { useEffect } from "react";
import { useRouter } from "next/navigation";
import { useUser } from "@clerk/nextjs";

export default function CallbackPage() {
  const router = useRouter();
  const { isLoaded, isSignedIn, user } = useUser();

  useEffect(() => {
    if (isLoaded && isSignedIn) {
      fetch("/api/user-callback", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          userId: user.id,
          emailAddress: user.emailAddresses[0].emailAddress,
        }),
      })
        .then((response) => response.json())
        .then(() => {
          router.push("/");
        })
        .catch((error) => {
          console.error("Error:", error);
        });
    }
  }, [isLoaded, isSignedIn, user, router]);

  return <div>Processing...</div>;
}

```

We'll create a file at:`app/api/user-callback/route.ts`  Which will create a Passport instance with KeySigner with your private key. PRIVATE\_KEY environment variable can point to a file path or the actual private key. Note that the private key should only be handled in your backend, and can't be exposed publicly.

```typescript
import { NextResponse } from "next/server";
import { KeySigner } from "@0xpass/key-signer";
import { Passport } from "@0xpass/passport";

export async function POST(req: Request) {
  const payload = await req.json();
  const keySigner = new KeySigner(process.env.PRIVATE_KEY!, true);

  const passport = new Passport({
    scope_id: process.env.NEXT_PUBLIC_SCOPE_ID!,
    signer: keySigner,
  });

  await passport.setupEncryption();
  const data = await passport.delegatedRegisterAccount({
    username: payload.emailAddress,
  });

  return NextResponse.json(data);
}
```

After authenticating with Clerk, you can directly interact with Passport with the username (email from Clerk) and your developer keys.

Now we'll implement `get-account`endpioint at `app/api/get-account/route.ts`.  For retrieving your user's email address you can use `currentUser()` function which will grab user information from the session established with Clerk.&#x20;

```typescript
import { currentUser } from "@clerk/nextjs/server";
import { KeySigner } from "@0xpass/key-signer";
import { Passport } from "@0xpass/passport";

export async function GET() {
  try {
    const user = await currentUser();
    if (!user) {
      return new Response("Unauthorized", { status: 401 });
    }

    const keySigner = new KeySigner(process.env.PRIVATE_KEY!, true);
    const passport = new Passport({
      scope_id: process.env.NEXT_PUBLIC_SCOPE_ID!,
      signer: keySigner,
    });

    passport.setUserData({ username: user.emailAddresses[0].emailAddress });
    await passport.setupEncryption();
    const addresses = await passport.getAddresses();
    return new Response(JSON.stringify(addresses), { status: 200 });
  } catch (error) {
    console.log(error);
    return new Response("Something went wrong", { status: 500 });
  }
}

```

Lastly, we're using `signing message` as an example of user action. In `app/api/sign/route.ts`, implement the following function.&#x20;

```typescript
import { NextResponse } from "next/server";
import { currentUser } from "@clerk/nextjs/server";
import { KeySigner } from "@0xpass/key-signer";
import { Passport } from "@0xpass/passport";
import { stringToHex } from "viem";

export async function POST(req: Request) {
  const payload = await req.json();
  const { type, data } = payload;

  const user = await currentUser();

  if (!user) {
    return new Response("Unauthorized", { status: 401 });
  }

  const keySigner = new KeySigner(process.env.PRIVATE_KEY!, true);
  const passport = new Passport({
    scope_id: process.env.NEXT_PUBLIC_SCOPE_ID!,
    signer: keySigner,
  });

  passport.setUserData({ username: user.emailAddresses[0].emailAddress });
  await passport.setupEncryption();
  const signature = await passport.signMessage(stringToHex(data));
  return NextResponse.json({ signature });
}
```

### Middleware

Under  app directory, we need a middleware to keep the authenticated user context across the backend apis and the frontend.

```typescript
import { authMiddleware } from "@clerk/nextjs/server";

export default authMiddleware({
  publicRoutes: ["/", "/auth/callback", "/lambda"],
});

export const config = {
  matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};

```

### Frontend

### Clerk Providers

First we'll need to make sure we wrap our application inside the `ClerkProvider` . We can do this by creating a new file `providers.tsx` inside the `src` directory, and populating it as below.

```typescript
"use client";
import { ClerkProvider } from "@clerk/nextjs";

export function Providers({ children }: { children: JSX.Element }) {
  return <ClerkProvider>{children}</ClerkProvider>;
}
```

Then we can now wrap our app with our Provider by going to `src/layout.tsx` and adjusting it so it looks like this&#x20;

```typescript
import { Inter } from "next/font/google";
import { Providers } from "./providers";
import localFont from "next/font/local";
import "./globals.css";

const myFont = localFont({ src: "../../public/fonts/PPNeueMontreal-Book.otf" });

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <Providers>
        <body className={`${myFont.className} bg-black text-white`}>
          {children}
        </body>
      </Providers>
    </html>
  );
}
```

Now in our **`page.tsx`** we can setup our state variables for, tracking registering, and authenticating users.&#x20;

```typescript
"use client";
import { useState } from "react";
import { SignUpButton, useUser, SignOutButton } from "@clerk/nextjs";
import { useEffect } from "react";

export default function Page() {
  const { isSignedIn, isLoaded } = useUser();
  const [authenticated, setAuthenticated] = useState(false);
  const [signMessageLoading, setSignMessageLoading] = useState(false);
  const [message, setMessage] = useState("");
  const [messageSignature, setMessageSignature] = useState({
    signature: "",
    timeTaken: 0,
  });
  const [address, setAddress] = useState<string>();
  const [addressLoading, setAddressLoading] = useState(false);
```

For fetching the address of the current user, we'll use the function below

```typescript
  const fetchDelegatedAddress = async () => {
    setAddressLoading(true);
    try {
      if (!addressLoading) {
        const response = await fetch("/api/get-account", {
          method: "GET",
        });

        if (response.ok) {
          const addresses = await response.json();
          setAddress(addresses.result[0]);
        }
      }
    } catch (error) {
      console.log(error);
    } finally {
      setAddressLoading(false);
    }
  };
```

and we'll trigger this function once when the page loads:

```typescript
  useEffect(() => {
    if (isSignedIn) {
      fetchDelegatedAddress();
    }
  }, [isSignedIn]);
```

We also need a handler for when user click on sign button:

```typescript
  async function delegatedSignMessage(message: string) {
    setSignMessageLoading(true);
    try {
      const startTime = performance.now();
      let response = await fetch("/api/sign", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          type: "message",
          data: message,
        }),
      });

      if (response.ok) {
        const { signature } = await response.json();
        const timeTaken = performance.now() - startTime;
        setMessageSignature({
          signature: signature.result,
          timeTaken: timeTaken,
        });
      } else {
        throw Error(`HTTP error: ${response}`);
      }
    } catch (e) {
      console.error(e);
    } finally {
      setSignMessageLoading(false);
    }
  }
```

Lastly, we'll work on the presentation of this page.&#x20;

Before we get to the main part, we'll display a spinner to wait for Clerk to determine whether this person is authenticated or not.

```typescript
  if (!isLoaded) {
    return (
      <div className="h-screen w-full flex items-center justify-center">
        <svg
          className="animate-spin h-12 w-12 text-white"
          xmlns="http://www.w3.org/2000/svg"
          fill="none"
          viewBox="0 0 24 24"
        >
          <circle
            className="opacity-25"
            cx="12"
            cy="12"
            r="10"
            stroke="currentColor"
            strokeWidth="4"
          ></circle>
          <path
            className="opacity-75"
            fill="currentColor"
            d="M22 12c0-5.522-4.477-10-10-10-1.065 0-2.098.166-3.051.47l1.564 1.564A8 8 0 0112 4c4.418 0 8 3.582 8 8h-2z"
          ></path>
        </svg>
      </div>
    );
  }

```

Lastly we have a simple button and input interfaces for signing in and submitting signature requests!

```typescript

  return (
   <div className="flex flex-col items-center justify-center min-h-screen py-2 bg-white text-black">
      <div
        className={`text-2xl font-bold mb-8 ${
          authenticated ? "text-green-500" : "text-red-500"
        }`}
      >
        {authenticated ? "Authenticated" : "Not authenticated"}
      </div>
      <div className="text-center">
        <h1 className="text-3xl font-bold underline">
          Passport Protocol with Clerk Auth Quickstart
        </h1>
        <p className="mt-2 text-lg">
          This is a quickstart guide for the Passport Protocol SDK.
        </p>

        <div className="flex flex-col mt-4 space-y-4">
          {authenticated ? (
            <>
              <div className="flex flex-col space-y-4">
                <div className="flex items-center justify-between">
                  <div className="font-bold">Address</div>
                  <div>{address}</div>
                </div>
              </div>

              {messageSignature && (
                <div className="flex flex-col space-y-4 max-w-[60ch] break-words">
                  <div className="font-bold">Message Signature</div>
                  <div>{messageSignature.signature}</div>
                </div>
              )}

              <input
                value={message}
                onChange={(e) => setMessage(e.target.value)}
                className="border border-1 rounded p-2 border-black mb-4 ml-2 text-center"
                placeholder="Message to sign"
              />
              <button
                onClick={async () => await delegatedSignMessage(message)}
                disabled={signMessageLoading}
                className="border border-1 rounded p-2 border-black mb-4 ml-2"
              >
                {signMessageLoading ? "Signing..." : "Sign Message"}
              </button>
            </>
          ) : (
            <div className="mb-12 flex flex-col space-y-2 mt-8">
              <SignUpButton
                mode="modal"
                afterSignInUrl="/auth/callback"
                afterSignUpUrl="/auth/callback"
              >
                <button className="border border-1 rounded p-2 border-black mb-4 w-full">
                  Sign Up / In With Clerk
                </button>
              </SignUpButton>
              <SignOutButton>
                <button className="border border-1 rounded p-2 border-black mb-4 w-full">
                  Sign Out (Clear Cache)
                </button>
              </SignOutButton>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

```

### Complete Setup

Now with all of this setup we can setup our UI too, so the overall setup looks as below. In the final part of our setup, we've created the UI layer to interact with the above functions. We have buttons to register and authenticate, which dynamically interact with the state, to show loading states, as well as authenticated states, and finally when a message is signed, the user is also able to see the signed message signature.\
\
Please refer to <https://github.com/0xpass/passport-clerk-quickstart> for the complete setup.

You should be able to clone, update environment variable and run the example in less than a minute.

<figure><img src="/files/PFXHDuHUbol6qM4BUpMy" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.0xpass.io/guides-and-examples/quickstarts-and-examples/clerk-auth.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
