Add Fauna User Authentication to a Next.js App

Shadid Haque
InstructorShadid Haque
Share this video with your friends

Social Share Links

Send Tweet

To have actual users in our application we need to represent those users in our database. Fauna has quite a few ways you can do user authentication but we'll be creating our own using a few built-in Fauna helpers.

We'll start by setting up the necessary Fauna logic for users. We'll add a User collection as well as a functions.fsl file that we'll expose user sign up and log in. Here we'll see how Fauna gives us a built in Credentials document to handle email and password for a user. It also has a login function that it exposes to make that easy for us which will generate a token for a user on login.

After setting up our functions, we'll add an UnAuthRole as well as an AuthRole and give proper actions for each role.

[00:00] Next, we're gonna add authentication to our site. Now if you look at Fauna's documentation, they have pretty extensive guide on how to add authentication. They go over topics like attribute based access control or ABAC, RBAC, and also integrating with the 3rd party auth providers like Auth0, Cognito, but we're [00:20] not gonna go too deep into it. For our application, we're gonna add a very simple auth system. In our code, under source app, we create a new folder called sign in. This is going to contain our sign in page. Inside sign in folder, we create a new file called page dot JS. This is going to contain our sign in page component. [00:41] Now let's write the code for this new component. We're gonna call this component sign in page and we'll add a simple form with an input for email, input for password, and a submit button. And we're going to add a form action here, which we'll call a function called do sign in. [01:02] And let's just create this do sign in function. Next, we're gonna create another folder under source app and we're gonna call it sign up. This is for our sign up page and we're gonna create a new file called page. Js inside sign up folder. Let's write the code for this component. We're gonna call it sign up page [01:23] and we'll return a form that has email password and sign up button. We'll also add a username input in the form, and we have a form action that is referencing a function called do sign up. So let's go ahead and create this function. [01:44] Now let's go ahead and update our database resources so we can start implementing these forms. We're gonna go to our schema folder and create a new file called auth.fsl. Here we're gonna write collection user to create a new user collection in [02:04] fauna. Inside this squiggly bracket, we will define a unique constraint on the email field. This ensures that no 2 user document will have the same email. Next, we create an index by writing the keyword index followed by the name of the index. In [02:24] this case, our name is by email. In fauna, index is an efficient way to query the database by a specific field or fields. We want to query the users by email. So we're gonna write terms and then in the square bracket, dot email. Next, we're gonna create some fauna functions. So in fauna, you have the ability to create functions that are [02:44] embedded in your database. Under schema, we create a new file called functions dot fsl. Fauna functions have a similar syntax to a JavaScript function. So you start by writing the keyword function and then name of the function, in this case, user registration, and then round brackets. [03:04] And inside the round bracket we're gonna add in the params, so in this case it's gonna be username, email, and password, and then we're gonna do squiggly braces, and we're gonna write let user equals to user dot create, round bracket, squiggly bracket, and then we're gonna [03:24] put username and email. And then we're gonna write credentials dot create then round bracket and squiggly bracket. Credentials here is a built in fauna collection that is used to create JWT token for authentication. And inside the [03:44] create, we're gonna have a document field. The value for it is going to be the user variable, and then we're gonna have the password field. Value for it going to be password. And finally, we assign a role to this function. So at the top of the function, we're gonna write at role server. This decorator basically tells Fauna [04:04] that everything inside this function will have server level access. Next, let's create the login function. So similar idea, but this time, we're just gonna have email and password as per apps. Inside the function, we're going to query the user by [04:23] user's email and assign it to user variable. Now just to note, we can use this by email function on user because we have created an index on our user collection that is called by email. Without that index, this query would not work. [04:44] Next, we're gonna write credentials by document, and we're going to pass in the user variable. Now this query will get the credentials for the particular user, and we can add a bang sign here like TypeScript to check if the user exists. And then we're gonna write dot login and pass [05:04] in the password. Again, credentials is a built in collection in Fauna, and these built in methods are provided to you. In the login function, you can explicitly pass in the expiration time for this token. I'm going to make it 1 hour. [05:25] Next, we're going to create a new file called roles dot fsl. This is where we're gonna define permissions for authenticated and non authenticated users. We are first going to define the unauth role, And the unauth role only has privileges to call the user registration function, [05:51] and it has access to call the user login function. And next we're gonna create the auth role. And the auth role will have more privileges. So we're gonna give read, create, write, and delete [06:10] privilege to room collection. And we're gonna do the same for messages collection. And now I'm going to push all these database changes with fonta schema [06:30] push command, and I'm going to accept all these changes. And our database is going to get updated. So in our dotenv file, we have this Fauna key. However, this key is a server key, so it has server level privileges. So we wanna replace this [06:50] with a unauth role key. So that way an unauthenticated user will have unauth role level privileges. So in my terminal, I'm going to write Fauna shell to get inside the Fauna shell. And inside the Fauna shell, I'm going to write key dot create, and I'm going to define role as unauth role. [07:13] And this will create a secret for the unauth role. So we'll just copy and paste it in our dotenv file. And that's about it. In the next video, we're going to hook up the sign in and sign out forms with Fauna queries.