Anonymous

Anonymous Users

Make sure you're done with setup before configuring authentication methods

You can store sessions and users in the database without requiring the user to go through actual authentication.

This can allow you to build signed-out experiences that seamlessly transition to a logged-in experience. For example, an anonymous user can populate a shopping cart with items, and only after be required to sign in to complete the purchase.

This is an advanced feature, which brings additional complexity, so we don't recommend it to newcomers.

Anonymous users setup

Provider configuration

Add the provider config to the providers array in convex/auth.ts.

You can import the Anonymous provider from @convex-dev/auth/providers/Anonymous:

convex/auth.ts
import { Anonymous } from "@convex-dev/auth/providers/Anonymous";
import { convexAuth } from "@convex-dev/auth/server";
 
export const { auth, signIn, signOut, store } = convexAuth({
  providers: [Anonymous],
});

Sign in anonymously

Now you can trigger an anonymous sign-in via the signIn function.

Usually you'll want to do this before writing some data to the database.

src/SendMessage.tsx
import { useAuthActions } from "@convex-dev/auth/react";
import { useMutation } from "convex/react";
import { api } from "../convex/_generated/api";
 
export function SendMessage() {
  const { signIn } = useAuthActions();
  const sendMessage = useMutation(api.messages.send);
  return (
    <form
      onSubmit={(event) => {
        event.preventDefault();
        const formData = new FormData(event.currentTarget);
        const message = formData.get("message") as string;
        void signIn("anonymous").then(() => sendMessage({ message }));
      }}
    >
      <input name="message" placeholder="Some text..." type="text" />
      <button type="submit">Send</button>
    </form>
  );
}

In this example, we make sure the user is signed-in anonymously before sending a message.

Convert an anonymous user to a normal user

If the client is currently authenticated as an anonymous user, and then signs in with an another authentication method, the anonymous user can be converted to a normal user. To support this flow, you must provide a custom account linking implementation.

Abuse prevention

Enabling anonymous users allows any client to write data into your database without authentication, which could be abused by malicious actors.

To prevent this, you can enable some form of CAPTCHA (opens in a new tab), you can leverage services such as hCaptcha (opens in a new tab) or Cloudflare Turnstile (opens in a new tab). After integrating the CAPTCHA into your frontend, you can pass a token to the signIn function:

src/SomeComponent.tsx
signIn("anonymous", { token });

And you can then validate it in the profile method of the provider config.

This example matches the Cloudflare Turnstile API:

convex/auth.ts
import { Anonymous } from "@convex-dev/auth/providers/Anonymous";
import { convexAuth } from "@convex-dev/auth/server";
 
export const { auth, signIn, signOut, store } = convexAuth({
  providers: [
    Anonymous({
      profile({ token }) {
        let formData = new FormData();
        formData.append("secret", process.env.CLOUDFLARE_TURNSTILE_SECRET);
        formData.append("response", token);
        const url = "https://challenges.cloudflare.com/turnstile/v0/siteverify";
        const response = await fetch(url, {
          body: formData,
          method: "POST",
        });
        const { success } = await response.json();
        if (!success) {
          throw new Error("Didn't pass CAPTCHA");
        }
        return { isAnonymous: true };
      },
    }),
  ],
});

When you're done configuring your chosen authentication methods, learn how to use authentication in your frontend and backend, including how to distinguish anonymous users, in Authorization.