Skip to content

Latest commit

 

History

History
116 lines (84 loc) · 5.58 KB

working.md

File metadata and controls

116 lines (84 loc) · 5.58 KB

Working

Table of Contents

Authentication

Bug Squash uses NextAuth.js for authentication. NextAuth.js supports authentication with Google, GitHub, Facebook, Twitter, Apple, Discord, Slack, and many other providers. You can also use email and password authentication, or create your own custom authentication provider.

Project only uses Google and GitHub authentication. To add authentication with other providers, you can add a new provider in app/(pages)/api/auth/[...nextauth]/route.ts. You can find more information about adding providers here.

Users are stored in a MongoDB database. You can find more information about configuring the database here. The schema is predefined by NextAuth.js, but custom callbacks can be added to the database configuration to add custom fields to the user object. The schema is:

interface User {
	_id: ObjectId;
	name: string;
	email: string;
	image: string;
	emailVerified: string;
}
interface Account {
	_id: ObjectId;
	provider: string;
	type: string;
	providerAccountId: string;
	accessToken: string;
	token_type: string;
	scope: string;
	userId: ObjectId;
}

MongoDB can be used like this seemlessly with next-auth.js using Adaptors. You can find more information about using MongoDB with next-auth.js here.

Information about a user's session can be retrieved through NextAuth.js's getServerSession function or useSession hook. You can find more information about these hooks here as well.

In short, getServerSession is used on the server side, and useSession is used on the client side. getServerSession returns a session object, and useSession returns an array containing the session object and a boolean indicating whether the session is loading.

The schema for the session object's user is:

interface User {
	name: string;
	email: string;
	image: string;
}

By default, the session object only contains the user's name, email, and image. You need to add a custom callback to add more fields to the session object. You can find more information about custom callbacks here.

One of the most important callback is for adding id to the session object. Which can be used to identify the user in the database. The callback is:

async function jwt(token: JWT, user: User) {
	// JWT forwards the token to the session
	if (user) {
		token.id = user.id;
	}
	return token;
}

async function session(session: Session, user: User) {
	// Forwarded user.id is added to the session
	session.user.id = user.id;
	return session;
}

But even after all this, for me the id was only avaible when fetching session through the useSession hook. getServerSession returned a session without the id.

SessionProvider

The SessionProvider component is used to wrap the application in a Provider component from NextAuth.js. The Provider component is used to provide the session object to the application. The SessionProvider component is defined in app/providers/provider.tsx. It is used in app/(pages)/layout.tsx to wrap the application. The SessionProvider component is defined as:

Just an addition step for next-auth.js to work with next.js

Pages

Next auth has predefined pages for authentication. You can find more information about these pages here. You can also create your own custom pages. You can find more information about custom pages here. The pages are:

  • /api/auth/signin: The sign in page.
  • /api/auth/signout: The sign out page.
  • /api/auth/callback: The callback page.
  • /api/auth/error: Error code passed in query string as ?error=
  • /api/auth/verifyRequest: Used to check email verification requests.
  • /api/auth/newUser: Users are redirected to this page if they are a new user.

Environment Variables

Already explained all the environment variables used and why here. But one thing with them is that when used directly, they flag TypeScript errors for possibly not being defined.

So, to fix that, I used a npm module called zod to define the environment variables. You can find more information about zod here. All it does is verify if the environment variables are non empty, and export a custom env object. Code for it is here.

Data Fetching

Since the id of the user is only accessible through the useSession hook, the data fetching functions are required to be done on client side. So, originally all the data was fetched by useEffect hooks, but that lead to messy code, but more importantly, always showed loading states on each page visit. Migrating the code to use useSWR hooks fixed that. You can find more information about useSWR hooks here.

Example of fetching data using useSWR hooks:

const fetcher = (url: string) => fetch(url).then((res) => res.json());

const { data: bug, error } = useSWR(() => (session ? `/api/bugs/${id}` : null), fetcher);