Sign In with Solana - Authenticate Users with their Phantom Wallet
Tags: solana, web3, thirdweb, auth
Published: 2022-10-13 01:36:16

## Introduction

In this guide, we are going to use thirdweb auth to add sign in with Solana to our Dapps!

Before we get started, below are some helpful resources where you can learn more about the tools we will use in this guide.

- [View project source code](https://github.com/thirdweb-example/sign-in-with-solana)
- [Solana SDK](https://portal.thirdweb.com/solana)
- [Getting Started with Solana](https://blog.thirdweb.com/guides/getting-started-with-solana/)

Let's get started!

### Why use web3 sign-in?

Sign-in with Solana allows you to securely log in using a wallet and verify the wallet on the backend! We are going to use Thirdweb Auth which uses the very popular JWT standard! JSON Web Token (JWT) is an open standard that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.

## Setup

### Creating Next.js App

I am going to use the [Next typescript solana starter template](https://github.com/thirdweb-example/next-typescript-solana-starter) for this guide.

If you are following along with the guide, you can create a project with the
[Next TypeScript template](https://github.com/thirdweb-example/next-typescript-starter) using the [thirdweb CLI](https://portal.thirdweb.com/cli):

```
npx thirdweb create --template next-typescript-solana-starter
```

If you already have a Next.js app you can simply follow these steps to get started:

- Install the thirdweb sdks: `@thirdweb-dev/react` and `@thirdweb-dev/sdk`
- Install packages for solana wallet adapter: `@solana/wallet-adapter-react`, `@solana/wallet-adapter-react-ui` and `@solana/wallet-adapter-wallets`.
- Wrap the [app](https://github.com/thirdweb-example/next-typescript-solana-starter/blob/main/pages/_app.tsx) in the `ThirdwebProvider` and `WalletModalProvider`.

### Setting up thirdweb auth

Firstly, we need to install the thirdweb auth package:

```
npm i @thirdweb-dev/auth # npm

yarn add @thirdweb-dev/auth # yarn
```

Now, create a file called `auth.config.ts` and the following:

```
import { ThirdwebAuth } from "@thirdweb-dev/auth/next";

export const { ThirdwebAuthHandler, getUser } = ThirdwebAuth({
  privateKey: process.env.PRIVATE_KEY as string,
  domain: "example.org",
});
```

- Update the domain with your domain.

- We need the private key of our wallet. So, go to your phantom wallet (if you haven't already created one, check out [this guide](https://blog.thirdweb.com/guides/getting-started-with-solana)) and click on the top right badge and select your wallet. Then click on the export private key button:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1665622606918/XihvLKPfE.png)

Copy this private key, and paste it into a new file .env in the following format:

```
PRIVATE_KEY=<your-private-key>
```

Using private keys as an env variable is vulnerable to attacks and is not the best practice. We are doing it in this guide for the sake of brevity, but we strongly recommend using a [secret manager to store your private key](https://portal.thirdweb.com/sdk/set-up-the-sdk/securing-your-private-key).

To configure the auth api, create a new folder inside `pages/api` called auth and `[...thirdweb].ts` file inside it! Here we need to export the thirdwebHandler that we created!

```
import { ThirdwebAuth } from "@thirdweb-dev/auth/next/solana";

export const { ThirdwebAuthHandler, getUser } = ThirdwebAuth({
  privateKey: process.env.PRIVATE_KEY as string,
  domain: "example.org",
});
```

Finally, inside the `_app.tsx` file, add the authConfig prop to `ThirdwebProvider`:

```
  <ThirdwebProvider
      network={network}
      authConfig={{
        authUrl: "/api/auth",
        domain: "example.org",
        loginRedirect: "/",
      }}
    >
      <WalletModalProvider>
        <Component {...pageProps} />
      </WalletModalProvider>
    </ThirdwebProvider>
```

## Building the frontend

Inside `pages/index.tsx` update the return statement with the following:

```
return (
  <div>
    {publicKey ? (
      <button onClick={() => login()}>Sign in with Solana</button>
    ) : (
      <WalletMultiButton />
    )}
  </div>
);
```

We are going to use the `useWallet` and `useLogin` hooks to get the login function and user address:

```
const { publicKey } = useWallet();
const login = useLogin();
```

We need to import these hooks like this:

```
import { useWallet } from "@solana/wallet-adapter-react";
import { useLogin, useUser } from "@thirdweb-dev/react/solana";
```

This will add sign-in with Solana to our site! Now we need to check if a user exists, so for that get the user from the `useUser` hook like this:

```
const { user } = useUser();
```

And we will check if the user exists and if it exists we will return this:

```
if (user) {
  return (
    <div className={styles.container}>
      <p>You are signed in as {user.address}</p>
      <button onClick={validateUser}>Validate user</button>
    </div>
  );
}
```

## Creating api for validation

Let's now create an api to get the user details (address) on the backend! So, create a new file called `validate.ts` inside `pages/api` and add the following:

```ts
import type { NextApiRequest, NextApiResponse } from "next";
import { getUser } from "../../auth.config";

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
  if (req.method === "POST") {
    const thirdwebUser = await getUser(req);

    if (thirdwebUser?.address) {
      return res.status(200).json({
        message: `You are signed in as ${thirdwebUser.address}`,
      });
    }
    return res.status(401).json({ message: "Account not validated" });
  }
  return res.status(405).json({ message: "Method not allowed" });
};

export default handler;
```

Here, we are using the getUser method from thirdweb to get the user's address and if it exists we send a message that "you are signed in as address".

## Calling the API on frontend

Create a new function called `validateUser` in `pages/index.tsx` like this:

```
const validateUser = async () => {
  try {
    const response = await fetch("/api/validate", {
      method: "POST",
    });

    const data = await response.json();
    alert(data.message);
  } catch (error) {
    console.log(error);
  }
};
```

And attach this function to onClick of the validate button:

```
<button onClick={validateUser}>Validate user</button>
```

## Conclusion

In this guide, we learned how to use thirdweb auth to add sign in with solana. Share your amazing Dapps that you built using sign in with solana on the [thirdweb discord](https://discord.gg/thirdweb)! If you want to take a look at the code, check out the [GitHub Repository](https://github.com/thirdweb-example/sign-in-with-solana).