Error occured: CredentialsSignin when trying to log in using Phantom provider

51 views Asked by At

I'm developing an application in Next.js 14 for one project. You need to authenticate using the Phantom wallet for the Solana blockchain. On localhost:3000 everything works correctly and on preview deploy in vercel, everything works correctly, but on the main domain the following error occurs.

enter image description here

I thought use Moralis, but it have big bundle.

next auth

export const authOptions: AuthOptions = {
  providers: [
    CredentialsProvider({
      name: 'web3',
      credentials: {
        signature: {
          label: 'Signature',
          type: 'text'
        },
        message: {
          label: 'Message',
          type: 'text'
        }
      },
      async authorize(credentials, req) {
        if (!credentials?.message) {
          return null
        }
        const { publicKey, host } = JSON.parse(credentials?.message)

        const nextAuthUrl = new URL(getURL())

        if (host !== nextAuthUrl.host) {
          return null
        }
        const crsf = await getCsrfToken({ req: { ...req, body: null } })

        if (!crsf) {
          return null
        }
        const nonceUnit8 = Signature.create(crsf)

        const isValidate = await Signature.validate(
          {
            signature: credentials?.signature,
            publicKey
          },
          nonceUnit8
        ).then((res) => res.valueOf)

        if (!isValidate) {
          throw new Error('Could not validate the signed message')
        }

        return { id: publicKey }
      }
    })
  ],

  session: { strategy: 'jwt' },

  debug: process.env.NEXT_PUBLIC_VERCEL_ENV === 'development',

  callbacks: {
    async session({ session, token }) {
      if (session.user) {
        session.user.name = token.sub
        session.user.image = `https://ui-avatars.com/api/?name=${token.sub}`
      }
      return session
    }
  }
}

Fn for connect wallet

import base58 from 'bs58'
import { getCsrfToken, signIn } from 'next-auth/react'

import { getProvider } from '../hooks/getProvider'
import { Signature } from './Signature'

export const onConnect = async () => {
  try {
    const provider = getProvider()

    if (!provider) {
      window.open('https://phantom.app/', '_blank')
    }

    const resp = await provider.connect()
    console.log('Connect', resp.publicKey.toString())
    const csrf = await getCsrfToken()
    if (resp && csrf) {
      const noneUnit8 = Signature.create(csrf)
      const { signature } = await provider.signMessage(noneUnit8)
      const serializedSignature = base58.encode(signature)
      const message = {
        host: window.location.host,
        publicKey: resp.publicKey.toString(),
        nonce: csrf
      }
      const response = await signIn('credentials', {
        message: JSON.stringify(message),
        signature: serializedSignature,
        redirect: false
      })
      console.log(response)
      if (response?.error) {
        console.log('Error occured:', response.error)
        return
      }
    } else {
      console.log('Could not connect to wallet')
    }
  } catch (error) {
    console.error(error)
  }
}

This getURL()

export const getURL = () => {
  if (process.env.NEXT_PUBLIC_VERCEL_ENV === 'development')
    return 'http://localhost:3000'
  else return `https://${process.env.NEXT_PUBLIC_VERCEL_URL}`
}

0

There are 0 answers