Part 5 — Authentication: Logging In + Signing Up

This will be a very simple implementation of authentication — just to provide an entry level understanding to cookies, sessions, and verification. When a user logs in or signs up they will be sent to a profile page. From there, they can view parts of the app only a verified user can have access to (in this example we’ll use a very simple CRUD forum page where users can post comments).

To start, create a “Profile.jsx” file. We’ve already created Login.jsx and Signup.jsx. The functionality in each of these files will be essentially the same. In Login.jsx declare a class component called Login. In this components state declare two keys, one for storing the userName and one for storing the password that the user types in. We will be updating these two stateful items with user input using onChange functions.

In your return function define two input tags, one for the userName and one for the password. In each of these tags declare an onChange function that, when called, updates state with the value of the input fields.

Login.jsx file

Next, add a button tag that, when clicked, takes the user to their profile page while passing their stateful information along. You will need to add a path for the Profile component in the index.js file using React Router. Add the same logic to the Signup component. To differentiate between the signup logic and the login logic in Profile.jsx, add a key to state to track whether the user is logging in or signing up. You can also add the button that leads to the signup page here so a user can create an account. Add a path for the signup page in the index.js file with React Router as well.

Login.jsx file

In Profile.jsx, declare a component called Profile. This component should be getting state as props from the Login and Signup components. You can console.log props to be sure you’re passing them correctly. In this file we will handle functionality to verify an existing user and create a new user. For this, we will declare two functions — “handleLogin” and “handleSignup”. In each of these functions, assign the userNames and passwords from props to new variables. Then, make a post request to a path for either login or signup. We’ll make routes for these paths in the backend next. For now, be sure to set the headers and send the username and password in the body of the post request.

Using a conditional, invoke handleLogin or handleSignup based on whether loggingIn or SigningUp is true in state.

We will simply render one button on this page, a button that leads to the forum page. In your return function, define a button tag that when clicked, leads to the forum page while sending stateful information along. Be sure to create a path with React Router for the forum page as well.

Profile.js file
Profile.js file

Now we can create the logic to handle the post requests we just created in our backend! In your server file you’ll need to set up routes. You can set up each routes in your server.js file or separate them (as I did) in different router files. To create separate routes first make a folder called “Routes” and within it, make two files — “apiRouter.js” and “userRouter.js”. These routes will handle all relevant requests made to their path. For example, the userRouter will handle all requests made to the user path. If you add the forum page later, you can make a forumRouter file that handles all requests to the forum path.

Next, in the server.js file, we need to create the routers that will direct the server to the appropriate routes. Meaning when a user clicks the login button, invoking a post request to the path ‘./user/login’, the backend will check the server.js file first. It will see that all requests to ‘/user’ will need the userRouter. It will then check the userRouter file to find the post route to the ‘/login’ path. You will set up routes in the userRouter for the login and signup paths.

In the server.js file, declare two variables and assign them to the router files you just created. Then, with the “app.use” method, define each router your app should use with each path. If you decide to make the forum page, create routes for that file as well. When defining your routers, order matters! The least specific router (the one with the least specific path) should be beneath the others. See lines 20–22.

server.js file

Now we can complete our router files and add Express.js middleware to them. In the apiRouter file simply add one route — a get to ‘./:id’ route that responds with a status of 200 (ok). The “:id” is so you can later access the users id number from the data base in the url string parameters.

apiRouter.js file

In the userRouter file add to two post requests, one for login and one for signup that responds with a status of ok.

userRouter.js file

Now we can add some middleware (controllers). The middleware will actually have the functionality that communicates with the database. To check if a user exists or to add a new user.

Create a folder called “Controllers” and add three files — “userController.js”, “cookieController.js”, and “sessionConroller.js” — to that folder. In userController.js require in the file you stored your database schema (mine is called “kyodieModels.js”). You will use this file to interact with the user model you created in your database. Next, create a controller called verifyUser. In this controller, destructure the username and password you stored in the request body (in Login.jsx). Use the “findOne” mongoose method to search your user database model for the one user with those credentials. If that user does not exist, console.log “user doesn’t exist”. Otherwise, save that users data to res.locals under a new variable name like “auth”. You can also update the url string parameters to include the users id number if you want. Console.log data in this controller to see that it is the complete document from the data base for that user — including the username, password, user id, and whatever else you add to that model.

Create another controller called “createUser” that adds a user to the database using the “create” method.

userController.js file

Create controllers for sessions and cookies in the same way. Sessions are a simple way to store data for individual users against a unique session ID. Cookies are small pieces of data sent from a website and stored on the user’s computer by the user’s web browser while the user is browsing.

We’ll store the users id in a session. We’ll store that sessions id in a cookie. We’ll use this information to verify if a user is logged in. For example, when a user is on the forum page, if they want to post a comment we will first check their session to see if they are currently logged in. If they are, they’ll be allowed to post a comment.

sessionController.js file
cookieController.js file

Lastly, add the controllers to their corresponding routes in userRouter.js. If you make the forum page add the corresponding controllers the forum routes as well.

userRouter.js file

Now, when a user logs in or signs up, we start a session (with their user id), create a cookie (with that sessions id), and respond to our post requests with an ok status. From here, users can have access to any private links or pages (like the forum page).

Finally! You’ve done it! You’ve finished the auth section and now have a pretty good entry level understanding Express routes and middleware, sessions, and cookies.

The forum page is a CRUD app in itself. Build that page on your own to put what you’ve learned in previous steps to the test. Follow along with my code when you need to. Or make your own private pages for logged in users to see. You can also play around with the styling and make it your own. Get creative!

Congrats! You now have a full stack app under your belt!

Build it out. Add more pages. Add more models to your data base. Make it you own.

Leave comments below and show off pics of what you made!

--

--