Solana Wallet Web2 Authentication

Hey there, are you tired of dealing with clunky and outdated authentication methods for your web2 apps? Look no further than Solana! In this guide, we'll show you how to implement Solana's cutting-edge authentication features in your web2 app in a few simple steps.

First, let's set up the frontend. We'll be using Next.js and TypeScript for this example. Here's the code for creating a login transaction:

const createLoginTx = async (wallet: WalletContextState) => {
  // A message that will be included in the login transaction
  // You can change it to anything you like, in this case it's "YOUR_SIGN_MESSAGE"
  const loginSignMessage = "YOUR_SIGN_MESSAGE";

  // A unique code that will be included in the login transaction
  // This code is generated by taking the current time in milliseconds, dividing it by 12e4 (1200,000)
  // and taking the floor of the result
  // This ensures that the code changes every 20 minutes
  const code = Math.floor( / 12e4);

  // Encode the message and the code as a Uint8Array
  const msg = new TextEncoder().encode(`${loginSignMessage} ${code}`);

  // Get the public key from the wallet object
  const pk = wallet.publicKey;

  // Check if the wallet object has a public key and a signMessage method
  if (!pk || !wallet.signMessage) {
    throw new Error("Wallet does not support signMessage");
  // Sign the message using the wallet's signMessage method
  const signed = await wallet.signMessage(msg);

  // Send a post request to the backend, including the public key and the encoded signature
  await`/web3/auth/v2/${pk.toBase58()}`, {
    signature: encode(signed),

This line of code

const code = Math.floor( / 12e4);

is responsible for generating a unique code every 20 minutes. It takes the current time in milliseconds using and divides it by 12e4 (1200,000) to get the number of 20-minute intervals since January 1st, 1970. The Math.floor() function is then used to round down to the nearest whole number. This ensures that the code changes every 2 minutes, providing a time-stamped code to be included in the login transaction for authenticity and integrity checking.

On the backend, we'll use the following code to verify the signature:

const nacl = require('tweetnacl');
const bs58 = require('bs58');

const express = require('express');
const app = express();'/web3/auth/v2/:publicKey', (req, res) => {
    const { publicKey } = req.params
    const { signature } = req.body

    // check if the request contains the publicKey and signature
    if (!publicKey || !signature) throw new Error('Invalid request')

    // message to be verified
    const loginSignMessage = 'YOUR_SIGN_MESSAGE'

    // code generated by the backend
    const code = Math.floor( / 12e4)

    //encode the message and the code
    const msg = new TextEncoder().encode(`${loginSignMessage} ${code}`)

    //decode the publicKey and the signature
    //verify the signature
    const ok = sign.detached.verify(msg, decode(signature), decode(publicKey))

    //if the signature is not verified throw an error
    if (!ok)
      throw new Error(
        'Invalid signature, please try again or contact support if the problem persists.'

    /* TO DO Your Session Codes */

app.listen(3000, () => {
  console.log('Server started on port 3000');

The backend first checks if the request contains the publicKey and signature, if it doesn't it throws an error. Then it defines the message to be verified, constructed by "YOUR_SIGN_MESSAGE" and the code generated by the backend, encodes the message and the code, decodes the publicKey and the signature, verifies the signature, and if the signature is not verified, it throws an error. In this way, the backend can ensure that the message was signed by the correct person and that it hasn't been tampered with, providing a secure way for the user to authenticate in the Web2 app.

In summary, the backend code uses the publicKey and the signature sent by the client to verify the authenticity of the message and the integrity of the code, by comparing it with the one generated by the backend, providing a secure and reliable way for users to authenticate in the Web2 app using Solana.