I've decided to start documenting my journey as the CTO of Grow. Here is the second build log (build log 2#) where I discuss in detail the development process of how I built the authentication layer for our dashboard.
What is Grow?
This is a tweet from our CEO at Grow describing what Grow is.
In this build log, I'll go through the authentication layer for the Grow dashboard. The Grow dashboard is where authenticated users (registered Grow students) have access to course materials, recorded lecture sessions, course agendas, student progress logs, etc. At the time of this publication, the Grow dashboard is still in the infant stages of its development.
Paul-Simon Emechebe@ptbthefirstJust built a pretty decent form validation with the @supabase database. For someone that has used Firebase all his life, Supabase made Postgres easy.13:00 PM - 17 Oct 2022
In this build log, I'll be covering the following;
1. The tech stack
2. The login page UI
3. The authentication flow
4. The validation logic
The tech stack
The four main dependencies are React, Next.js, Tailwind, and Supabase.
- Next.js: Next.js is a web framework built on top of React. Amongst a lot of the features it provides, the most notable one is SSG (server-side rendering). One of the best features Next.js provides is its file-based routing system.
- Tailwind: Tailwind is a CSS framework that gives you the ability to inline-style using pre-built utility classes. Learn more about Tailwind here
Supabase: Supabase is a suite of open-source tools/software to help you build apps using Postgres. The Supabase database is what we used to store all the data for our registered students. They also offer authentication but I didn't see the need to do my user validation on Supabase, I just needed Supabase to give me all our users, then I'd handle the validation logic on the client.
Why? I'll touch on that in the authentication flow section. Learn more about Supabase here
The login page UI
In this section, I go through the process of building the UI of the login page i.e styling, folder structure, and component structure.
At the time of this publication, the UI of the login page was not yet built with our custom UI components (e.g
FormLabel). So a lot is happening in this single file. No custom hooks, no reusable UI components, and no helper functions. All the logic was done in this single file. This is bad practice for it will catch up with you once you start scaling. Below will show you screenshots of the file.
DISCLAIMER: I am not encouraging this approach to building components. I am just citing an example of what not to do. I built it like this temporarily, just to get something running. Depending on the time you are reading this, the UI must have been written with good scalable practices.
Usestate. This is meant to be avoided by dedicating specific state logic to custom hooks.
- Redundant styling and HTML. This is meant to be avoided by building custom UI components that carry identical styling and possibly logic for the sole purpose of them being reusable. From the picture below. line 131 signifies the start and line 267 signifies the end. Do the math, that's a total of 136 lines of code for just a login page. That's too many lines of code.
Here I go through the user journey of the login page.
These are the steps that the User undergoes to get authenticated as a student.
- Step 1: The user does a manual registration in the venue of the Bootcamp and gets an OTP code.
- Step 2: The user goes to the Grow Dashboard login page.
- Step 3: The user logs in with the first name he/she used for the manual registration and the OTP code.
In this section, I discuss the logic I wrote to securely validate that the user logging in is indeed who he/she claims ( input ) to be.
First of all, we'll take an overview of what happens behind the scene. Below is a diagram of two parties, the client ( the app ) and the database/server ( Supabase ). Supabase provides a feature called Supabase Auth that deals with authenticating users. I didn't use Supabase Auth to authenticate my users, why?
Due to the fact we are a young startup, we are targeting our students locally. So there was no need of integrating an online payment gateway so we did our payments in person. The in-person payment also requires the student to fill out a form citing the student's credentials. Once the student has done this, the student is officially registered. After this manual registration, the student will be sent an OTP to his/her email to verify his/her account and access his/her dashboard.
The user data for authentication were
- Students registered full name: The full name the student used for manual registration.
- OTP code: The code is sent to the student's email after manual registration has been completed.
NOTE: In the next build log ( build log #3 ), I'm going to discuss the validation logic in detail (line by line). The explanation below is just skimming through the important stuff.
As you can see above, Supabase doesn't handle the validation logic, all it does is provide all the credentials of manually registered students.
So what's happening on the client side?
- two functions handling the validation logic (
- one useEffect
- two components (
This function contains a Supabase API that does two things;
- reads a list of all the students registered on the database with their various credentials bound to each student.
- filters the list and spits out all the student's full name and OTP codes only after this API call is run, the filtered data is compared with the user's input. The comparison returns a boolean. so validation is done anytime the user triggers an
onChangeon the input field. More on this will be discussed in the next build log (build log 3#).
The logic from the
readSupabasefunction starts checking wether the user is valid or not once the user starts typing
below is when the validation is false
below is when the validation is true
This runs once the user clicks the login button. This function does several things;
- starts the loading state
- checks whether the full name exists in the database
- checks whether the OTP exists in the database
- checks whether the full name and OTP are bound to the same student
- starts a modal state
- redirects to the dashboard
NOTE: in the next build log, I'll go through these line by line
These two components handle the icons on the right of the input fields. They are responsible for displaying the;
- error icon: signifying that the user's input does not match what is in the database
- check icon: signifying that the user's input matches what's on the database.
As of the time of writing this, no refactoring was done whatsoever. It's the first iteration of the login page. I just wanted to get things running, in future build logs, I'll discuss how I refactored the login page. Thanks for reading, if you have any suggestions, criticism, or even ways to make these build logs add more value to you guys, feel free to let me know in the comment section below. Have a good day!
Top comments (0)