DEV Community

Cover image for Sign In with Solana - Authenticate Users with their Phantom Wallet
Avneesh Agarwal for thirdweb

Posted on • Originally published at blog.thirdweb.com

Sign In with Solana - Authenticate Users with their Phantom Wallet

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.

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 for this guide.

If you are following along with the guide, you can create a project with the
Next TypeScript template using the thirdweb CLI:

npx thirdweb create --template next-typescript-solana-starter
Enter fullscreen mode Exit fullscreen mode

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 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
Enter fullscreen mode Exit fullscreen mode

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",
});
Enter fullscreen mode Exit fullscreen mode
  • 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) and click on the top right badge and select your wallet. Then click on the export private key button:

image.png

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

PRIVATE_KEY=<your-private-key>
Enter fullscreen mode Exit fullscreen mode

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.

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",
});
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
);
Enter fullscreen mode Exit fullscreen mode

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

const { publicKey } = useWallet();
const login = useLogin();
Enter fullscreen mode Exit fullscreen mode

We need to import these hooks like this:

import { useWallet } from "@solana/wallet-adapter-react";
import { useLogin, useUser } from "@thirdweb-dev/react/solana";
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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:

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;
Enter fullscreen mode Exit fullscreen mode

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);
  }
};
Enter fullscreen mode Exit fullscreen mode

And attach this function to onClick of the validate button:

<button onClick={validateUser}>Validate user</button>
Enter fullscreen mode Exit fullscreen mode

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! If you want to take a look at the code, check out the GitHub Repository.

Top comments (0)