The Absolute Simplest React Auth Setup

One of the biggest hurdles to starting a new app is all the mundane setup required before you can truly get started. Setting up DNS, error tracking, hooking up a CMS, pulling in your favorite components and icons—the list goes on.

Today, we're going to completely remove one item from that list: setting up React auth. I'm going to outline a React auth setup that's so simple, you can get it live in under five minutes. And that's without sacrificing any security or user experience.

Here is what you will build in this tutorial:

  • passwordless auth
  • ... with backend to handle sign up, login, and logout
  • ... and React utils to handle all the frontend work

Prerequisites

We'll assume you are making a Next.js webapp, and that you have the basic app already scaffolded, using something like create-next-app.

To power our React auth, you will use Yolotp. If you don't already have a Yolotp account, register for one now.

Other than that, nothing is required!

1. Install dependencies

First, install the Yolotp bindings for Next.js:

npm i @yolotp/next

This package will do the heavy lifting for the auth workflow. It includes backend handlers that integrate with Next.js API routes, and a frontend hook that exposes everything required to use auth in the UI.

2. Add the Yolotp secret environment variable

In your .env file, add the Yolotp secret key:

YOLOTP_SECRET_KEY=your_secret_key

You can copy the secret key from your Yolotp dashboard at any time.

Make sure your environment variables name matches what's shown above: YOLOTP_SECRET_KEY. By default, the Next bindings look for an environment variable with this exact name.

If you're deploying on Vercel, add the secret key there too.

3. Create the backend route

Inside your Next app directory, create a new file: app/api/auth/route.ts.

It's very important that you create this file inside the app folder, rather than the legacy pages folder. Yolotp is meant to work with Next's App Router. You can still build the rest of your app inside the pages folder if you prefer—only this backend handler needs to live inside inside the app folder.

In this file, simply export the backend handlers:

export { GET, POST, DELETE } from "@yolotp/next/server";

Done! Let's move onto the frontend.

4. Frontend: Add the Yolotp hook

The @yolotp/next package includes a frontend hook that exposes all utilities you need to register, log in, and log out your users.

To begin using the hook, create a new page at app/login/route.ts. For now, just call the hook and render the user's current auth status:

export default function Page() {
	const { user, requestCode, loginWithCode, logout, status } = useYolotp();

	return (
		<main>
			<h1>Login Form</h1>
			<p>status: {status}</p>
		</main>
	);
}

When you open this page, you'll see the status briefly say Initializing, and then update to LoggedOutEmailNeeded—indicating the user is logged out, and you need their email before they can log in.

5. Frontend: Add The Email Form

With Yolotp, the first step of the React auth workflow is collecting an email. Update the page so the user can enter their email and receive a login code.

You need three new elements:

  1. A form to submit the email
  2. A callback to send the email to your backend
  3. A useState hook to save the email for the next step

Add all three of those now:

export default function Page() {
	const { user, requestCode, loginWithCode, logout, status } = useYolotp();
	const [checkCodeEmail, setCheckCodeEmail] = useState<string | undefined>();

	async function getCode(e: React.FormEvent<HTMLFormElement>) {
		e.preventDefault();

		const data = new FormData(e.currentTarget);
		const email = data.get("email") as string;
		await requestCode({ email });

		setCheckCodeEmail(email);
	}

	return (
		<main>
			<h1>Login Form</h1>
			<p>status: {status}</p>
			{status === SessionStatus.LoggedOutEmailNeeded && (
				<form onSubmit={getCode}>
					<div>
						<input name="email" type="email" placeholder="Email" />
					</div>
					<button type="submit">Continue</button>
				</form>
			)}
		</main>
	);
}

Now when you load the page and submit your email, you should see the status change from LoggedOutEmailNeeded to LoggedOutCodeNeeded. If you check your inbox, you should also receive an email with a login code—but you don't have any place to submit that code yet.

6. Frontend: Add The Code Form

To complete Yolotp login, the user needs to enter the code they received by email.

For that, you need two new elements:

  1. A form to submit the code
  2. A callback to send the code to your server

Add both of those now:

export default function Page() {
	const { user, requestCode, loginWithCode, logout, status } = useYolotp();
	const [checkCodeEmail, setCheckCodeEmail] = useState<string | undefined>();

	async function getCode(e: React.FormEvent<HTMLFormElement>) {
		e.preventDefault();

		const data = new FormData(e.currentTarget);
		const email = data.get("email") as string;
		await requestCode({ email });

		setCheckCodeEmail(email);
	}

	async function checkCode(e: React.FormEvent<HTMLFormElement>) {
		e.preventDefault();
		const data = new FormData(e.currentTarget);
		const code = data.get("code") as string;

		await loginWithCode({ email: checkCodeEmail!, code });
		setCheckCodeEmail(undefined);
	}

	return (
		<main>
			<h1>Login Form</h1>
			<p>status: {status}</p>
			{status === SessionStatus.LoggedOutEmailNeeded && (
				<form onSubmit={getCode}>
					<div>
						<input name="email" type="email" placeholder="Email" />
					</div>
					<button type="submit">Continue</button>
				</form>
			)}
			{status === SessionStatus.LoggedOutCodeNeeded && (
				<form onSubmit={checkCode}>
					<div>
						<input name="code" type="text" placeholder="Code" />
					</div>
					<button type="submit">Log In</button>
				</form>
			)}
		</main>
	);
}

Try it out: enter your email, get the code from your inbox (it should arrive within a few seconds), and then enter the code. You should see the status update from LoggedOutCodeNeeded to LoggedIn.

Elsewhere in your app, you can use this status enum to gate functionality that is only available to logged-in users. For example:

{status === SessionStatus.LoggedIn && (
	<a href="/dashboard">Go To Dashboard</a>
)}

7. Frontend: Add A Logout Button

Last, give your users a way to logout. A log out button, hooked up to the Yolotp logout callback, will do the trick:


export default function Page() {
	const { user, requestCode, loginWithCode, logout, status } = useYolotp();
	const [checkCodeEmail, setCheckCodeEmail] = useState<string | undefined>();

	async function getCode(e: React.FormEvent<HTMLFormElement>) {
		e.preventDefault();

		const data = new FormData(e.currentTarget);
		const email = data.get("email") as string;
		await requestCode({ email });

		setCheckCodeEmail(email);
	}

	async function checkCode(e: React.FormEvent<HTMLFormElement>) {
		e.preventDefault();
		const data = new FormData(e.currentTarget);
		const code = data.get("code") as string;

		await loginWithCode({ email: checkCodeEmail!, code });
		setCheckCodeEmail(undefined);
	}

	return (
		<main>
			<h1>Login Form</h1>
			<p>status: {status}</p>

			{status === SessionStatus.LoggedOutEmailNeeded && (
				<form onSubmit={getCode}>
					<div>
						<input name="email" type="email" placeholder="Email" />
					</div>
					<button type="submit">Continue</button>
				</form>
			)}

			{status === SessionStatus.LoggedOutCodeNeeded && (
				<form onSubmit={checkCode}>
					<div>
						<input name="code" type="text" placeholder="Code" />
					</div>
					<button type="submit">Log In</button>
				</form>
			)}

			{status === SessionStatus.LoggedIn && (
				<button onClick={() => logout()} type="button">
					Log Out
				</button>
			)}
		</main>
	);
}

With this, you have the full auth lifecycle implemented!

Notice a couple of things you did not have to build: password reset and email verification. Email verification is implicit in the passwordless login workflow—if the user can retrieve their code, their email is correct. And of course there is no password, so there's no password reset to worry about.

BONUS: Use your user's information in the app

The useYolotp hook includes one more piece of information you didn't use above: a user variable that includes information about the current user, like their email. When the hook initializes, this information is loaded fresh from Yolotp, and the hook refreshes it occasionally during the session in case the information changes.

Render that on the page too:

{user != null && (
	<div>
		<h3>User Info</h3>
		<ul>
			<li>email: {user.email}</li>
		</ul>
	</div>
)}

BONUS PART TWO: Manage Users In Your Yolotp Dashboard

Yolotp gives you a dashboard to manage your users. You can see when they signed up, how often they have logged in, and edit their basic details.

If you logged in during this tutorial, Yolotp saved the email you used as a user on your Yolotp account. Go to your Yolotp dashboard, and you will see the email listed there.

Wrap Up

That's everything you need to use Yolotp for your React auth.

If you have questions or got stuck along the way, reach out at jumbo@yolotp.com. I'll be glad to personally help you out!