DEV Community

Daanish2003
Daanish2003

Posted on

Anonymous login using better_auth, nextjs, prisma, shadcn

In this guide, we will implement Anonymous Login for a modern web application using a secure and developer-friendly stack. This feature will allow users to interact with your app without requiring immediate registration or authentication. By the end of this tutorial, your application will support seamless anonymous sessions that can be converted to authenticated accounts, providing an enhanced user experience while maintaining security and scalability.

Tech Stack

Here’s the technology stack we’ll be using:

  • Better_Auth v1: A lightweight and extensible TypeScript authentication library.
  • Next.js: A powerful React framework for building server-rendered applications.
  • Prisma: A modern ORM for efficient and type-safe database interaction.
  • ShadCN: A utility-first component library for rapid UI development.
  • TailwindCSS: A popular CSS framework for building modern user interfaces.
  • Resend: A reliable email service for sending OTPs.

Prerequisites

Before proceeding, ensure you have the following ready:

  1. Node.js (LTS version) installed.
  2. A package manager like npm, yarn, or pnpm (we'll use pnpm in this guide).
  3. A PostgreSQL database instance (local or hosted, such as Supabase or PlanetScale).
    • If you're working locally, Docker is a great way to set this up.
  4. Familiarity with TypeScript, Next.js, and Prisma.

Cloning the Starter Project:

This guide builds upon functionality such as Email-Password Authentication and Email Verification. You can:

git clone -b feat-username https://github.com/Daanish2003/better_auth_nextjs.git  
Enter fullscreen mode Exit fullscreen mode

Navigate to the project directory and install dependencies:

pnpm install  
Enter fullscreen mode Exit fullscreen mode

Setup

1. Configure the .env File

Create a .env file in the root of your project and add these configurations:

# Authentication settings
BETTER_AUTH_SECRET="your-secret-key" # Replace with a secure key
BETTER_AUTH_URL="http://localhost:3000"
NEXT_PUBLIC_APP_URL="http://localhost:3000"

# Database settings
POSTGRES_PASSWORD="your-password"
POSTGRES_USER="your-username"
DATABASE_URL="postgresql://your-username:your-password@localhost:5432/mydb?schema=public"

# Resend API Key
RESEND_API_KEY="your-resend-api-key"
Enter fullscreen mode Exit fullscreen mode

If you're using Docker for PostgreSQL, start the container:

docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Step 1: Update schema.prisma file

Open schema.prismafile in your project folder and then update the usermodel in schema by adding the isAnonymouscolumn with optional type string to it.

model User {
  id               String      @id @default(cuid())
  name             String
  email            String
  emailVerified    Boolean     @default(false)
  image            String?
  createdAt        DateTime    @default(now())
  updatedAt        DateTime    @updatedAt
  twoFactorEnabled Boolean     @default(false)
  username         String?
  // Add anonymous column to user model
  isAnonymous      Boolean?
  Session          Session[]
  Account          Account[]
  TwoFactor        TwoFactor[] // if you implemented 2FA add this column

  @@unique([email])
  @@map("user")
}
Enter fullscreen mode Exit fullscreen mode

Then, Generate and migrate the prisma file using command below

pnpx prisma generate
pnpx prisma migrate dev --name anonymous
Enter fullscreen mode Exit fullscreen mode

Step 2: Update auth.ts and auth-client.tsfile

Open auth.ts file in your project repository and then add the anonymous() plugin into plugin array of betterAuth function.

// src/lib/auth.ts
import { betterAuth } from "better-auth"
import { username } from "better-auth/plugins"

const auth = betterAuth({
    // other config options
    plugins: [ 
        // other plugins
        anonymous({
         // optional to add this
         emailDomainName: "exmaple.com" // Adding the email domain name to user
         //Note: user model, account model and session model is automatically transfer when user signup using their email. 
// There is no need to transfer the user, account, session model table data. 
// If you have other data of user then use the option below to transfer the data
         onLinkAccount: () => {
         // if you want transfer the guest users all the data like preference, carts, or items  after login. Please use this option to update data in your database
}
        }) 
    ] 
})
Enter fullscreen mode Exit fullscreen mode

Then, Open auth-client.ts file in your project repository and add anonymousClient() plugin function to the array of plugins

// src/lib/auth-client.ts
import { createAuthClient } from "better-auth/client"
import { anonymousClient } from "better-auth/client/plugins"

export const authClient = createAuthClient({
    baseURL: process.env.NEXT_PUBLIC_APP_URL,
    plugins: [ 
         // other plugin options
        anonymousClient() 
    ] 
})

export const {
    signIn,
    signOut,
    signUp,
    useSession
} = authClient;
Enter fullscreen mode Exit fullscreen mode

Step 4: Create anonymous-button Component

Create a anonymous-button.tsx inside the components/auth/ folder and paste the code from below

// src/components/auth/anonymous-button.tsx
import React from 'react'
import { Button } from '../ui/button'
import { User } from 'lucide-react'
import { authClient } from '@/lib/auth-client'
import { useAuthState } from '@/hooks/useAuthState'
import { useRouter } from 'next/navigation'

const AnonymousButton = () => {
    const router = useRouter();
    // handler error, success, and loading state
    const {setSuccess, setError, setLoading, resetState } = useAuthState();
    const handleSignInAnonymous = async () => {
        try {
            await authClient.signIn.anonymous({
                fetchOptions: {
                    onSuccess: () => {
                        setSuccess("LoggedIn successfully")
                        router.replace('/')
                    },
                    onError: (ctx) => setError(ctx.error.message),
                    onRequest: () => {
                        resetState()
                        setLoading(true)
                    },
                    onResponse: () => setLoading(true)
                }
            })

        } catch(error) {
            console.log(error)
            setError("Something went wrong")
        }

    }
  return (
    <Button className='w-28' onClick={handleSignInAnonymous}>
        <User />
        Guest
    </Button>
  )
}
export default AnonymousButton
Enter fullscreen mode Exit fullscreen mode

This Component handles the logic of anonymous login

Step 5: Update SignIn component and Signup component

SignUp Component:

// src/components/auth/sign-up.tsx
"use client"

// other imports
import AnonymousButton from "./anonymos-button";

const SignUp = () => {

    // Other functions and logics 

    return (
        <CardWrapper
            cardTitle='SignUp'
            cardDescription='Create an new account'
            cardFooterLink='/signin'
            cardFooterDescription='Already have an account?'
            cardFooterLinkTitle='Signin'
        >
            <Form {...form}>
                 <form className='space-y-4' onSubmit={form.handleSubmit(onSubmit)}> 
                 {/* FormFields example: Email, password and other*/} 
                 {/* Add the Anonymous login button below inside the form*/}
                 <AnonymousButton />
                 </form>
            </Form>
        </CardWrapper>
    )
}

export default SignUp
Enter fullscreen mode Exit fullscreen mode

Add AnonymousButton component to SignUp:

  • By clicking the anonymous button user were able to login anonymously

SignIn Component

// components/auth/sign-in.tsx

"use client";

// other imports
import AnonymousButton from "./anonymos-button";

const SignIn = () => {
    // other function

    return (
        <CardWrapper
            cardTitle="Sign In"
            cardDescription="Enter your email or username below to login to your account"
            cardFooterDescription="Don't have an account?"
            cardFooterLink="/signup"
            cardFooterLinkTitle="Sign up"
        >
            <Form {...form}>
                <form className="space-y-4" onSubmit={form.handleSubmit(onSubmit)}>
                    {/* Email or Username Field */}
                    {/* All other exisitng formfields like password and form message */}
                    {/* Add Anonynous button here */}
                    <AnonymousButton />
                </form>
            </Form>
        </CardWrapper>
    );
};

export default SignIn;
Enter fullscreen mode Exit fullscreen mode

Add AnonymousButton to SignIn:

  • By clicking the anonymous button user were able to login anonymously

Step 6: Run your application:

Start your development server:

pnpm dev
Enter fullscreen mode Exit fullscreen mode

Navigate to your sign-up route and sign-in route and try login anonymously

Conclusion

Congratulations! 🎉 You’ve successfully implemented Anonymous Login in your application. With this feature, users can explore and interact with your app without the need for immediate registration, enhancing accessibility and user engagement. Moreover, by enabling a smooth transition from anonymous sessions to authenticated accounts, your app ensures both flexibility and security for its users.

Blog Links:

Username and Password auth using BetterAuth: https://dev.to/daanish2003/username-and-password-authentication-with-betterauth-nextjs-prisma-shadcn-and-tailwindcss-1hc6

Two Factor Authentication using BetterAuth: https://dev.to/daanish2003/two-factor-authentication-using-betterauth-nextjs-prisma-shadcn-and-resend-1b5p

Forgot and ResetPassword using BetterAuth: https://dev.to/daanish2003/forgot-and-reset-password-using-betterauth-nextjs-and-resend-ilj

Email Verification Blog: https://dev.to/daanish2003/email-verification-using-betterauth-nextjs-and-resend-37gn

Email And Password with Better_Auth: https://dev.to/daanish2003/email-and-password-auth-using-betterauth-nextjs-prisma-shadcn-and-tailwindcss-hgc

OAuth Blog: https://dev.to/daanish2003/oauth-using-betterauth-nextjs-prisma-shadcn-and-tailwindcss-45bp

Reference Links:

Better_Auth Docs: https://www.better-auth.com/

pnpm Docs: https://pnpm.io/

Docker Docs: https://docs.docker.com/

Prisma Docs: https://www.prisma.io/docs/getting-started

Shadcn Docs: https://ui.shadcn.com/

Next.js Docs: https://nextjs.org/

Tailwindcss Docs: https://tailwindcss.com/

Github repository: https://github.com/Daanish2003/better_auth_nextjs

Top comments (0)