[SOLVED] User Authentication on SOLANA

import Moralis from "moralis";
const TIME = new Date();
const FUTURE = new Date(
  TIME.getFullYear(),
  TIME.getMonth(),
  TIME.getDate() + 7,
  TIME.getHours(),
  TIME.getMinutes(),
  TIME.getSeconds(),
  TIME.getMilliseconds()
);
const DOMAIN = process.env.APP_DOMAIN;
const STATEMENT = "Please sign this message to confirm your identity.";
const URI = process.env.NEXTAUTH_URL;
const EXPIRATION_TIME = FUTURE.toISOString();
const NOT_BEFORE = TIME.toISOString();
const TIMEOUT = 60;
export default async function handler(req, res) {
  const { address, chain, network } = req.body;
  await Moralis.start({ apiKey: process.env.MORALIS_API_KEY });
  try {
    if (!DOMAIN || !URI) {
      throw new Error("Please add APP_DOMAIN in the .env.local");
    }
    const message = await Moralis.Auth.requestMessage({
      address: address,
      solNetwork: chain,
      network: network,
      domain: DOMAIN,
      statement: STATEMENT,
      uri: URI,
      expirationTime: EXPIRATION_TIME,
      timeout: TIMEOUT,
      notBefore: NOT_BEFORE,
    });
    res.status(200).json(message);
  } catch (error) {
    console.log(error);
    res.status(400).json({ error });
  }
}
import { useEffect, useState } from "react";
import { useWallet } from "@solana/wallet-adapter-react";
import { WalletMultiButton } from "@solana/wallet-adapter-react-ui";
require("@solana/wallet-adapter-react-ui/styles.css");
import base58 from "bs58";
import { apiPost } from "../../utils/apiPost";
import { signIn } from "next-auth/react";
export default function WalletAdaptor() {
  const { publicKey, signMessage } = useWallet();
  const [signed, setSigned] = useState(false);
  const signCustomMessage = async () => {
    const address = publicKey.toBase58();
    const chain = "mainnet";
    const account = {
      address: address,
      chain: chain,
      network: "solana",
    };
    // const message = "Sign to provide access to app";
    const { message } = await apiPost("api/auth/request-message", account);
    const encodedMessage = new TextEncoder().encode(message);
    const signedMessage = await signMessage(encodedMessage, "utf8");
    setSigned(true);
    const signature = base58.encode(signedMessage);
    try {
      await signIn("credentials", {
        message,
        signature,
        redirect: false,
      });
    } catch (e) {
      console.log(e);
      return;
    }
  };
  useEffect(() => {
    publicKey ? !signed && signCustomMessage() : setSigned(false);
  }, [publicKey]);
  return (
    <>
      <WalletMultiButton />

    </>
  );
}
import CredentialsProvider from "next-auth/providers/credentials";
import NextAuth from "next-auth";
import Moralis from "moralis";
export default NextAuth({
  providers: [
    CredentialsProvider({
      name: "MoralisAuth",
      credentials: {
        message: {
          label: "Message",
          type: "text",
          placeholder: "0x0",
        },
        signature: {
          label: "Signature",
          type: "text",
          placeholder: "0x0",
        },
      },
      async authorize(credentials) {
        try {
          const { message, signature } = credentials;
          await Moralis.start({ apiKey: process.env.MORALIS_API_KEY });
          const { address, network, profileId, expirationTime } = (
            await Moralis.Auth.verify({ message, signature, network: "solana" })
          ).raw;
          const user = {
            address,
            network,
            profileId,
            expirationTime,
          };
          return user;
        } catch (e) {
          console.error(e);
          return null;
        }
      },
    }),
  ],
  callbacks: {
    async jwt({ token, user }) {
      user && (token.user = user);
      return token;
    },
    async session({ session, token }) {
      session.expires = token.user.expirationTime;
      session.user = token.user;
      return session;
    },
  },
  session: {
    strategy: "jwt",
  },
});

I have this code to allow new users to validate and verify with their solana wallets. The signtature pops up for signing and it is possibel to sign, but I always get further linked to http://localhost:3000/api/auth/error. I used the code from a youtubevideo: https://www.youtube.com/watch?v=0fuevxebv_E
Thanks for any helping hand.

is there any error server side in console?
can you add some logging with console.log to see where it stops working?

OHHHHH Man I found the problem, sorry for the time. […nextauth}.js I wrote it wrong, sorry super embarassing mistake. Thanks for your precious time. I ll keep on building and staying around. Obviously now it works :smile: :innocent:

1 Like