Building a Persisting User Login with React.
Published: 2023-03-30 17:31:44

Can one build a Persisting User Login feature using only React and JSON-Server as a local REST API? 

.....Yeah Obviously, otherwise I wouldn't be bothering to write this Blog about it. But should you? Probably not, there's a bunch framework/libraries that have been painstakingly built and tested by countless people to insure that they can securely do so with out risking users personal information or passwords being compromised. Still sometimes reinventing the wheel can be fun!

Writing a basic login feature isn't too difficult, assuming that you're already familiar with using React/Javascript to do Post and Get requests to a json-server database. Create a users array of obj on your db.json server with email as the unique identifier. Create a form with text inputs for e-mail, username and password. Hash the password, do some basic checks like insuring e-mail doesn't already exist, put it all together in an object Post it to /users and BAM you've got your account registration down!

But this blog isn't about creating user login feature it's about how to insure that once your user has logged in it persists.  So how do you get a user to not only login but remain logged in when your React State is instantly wiped clean anytime a user refreshes the page or closes the tab? 

The answer is that you need some way for the website to identify you as a unique user, so that it's still able to recognize you even if your react state is cleared on a refresh. Accomplishing this is as simple as creating a new array of objects in your db.json file called "status". Now when ever a user successfully logs into their account, your app will do a POST request to "status" with a id key that uniquely identifies the user (We'll get to that later) along with key/value pairs associated with their account. Now we just add an open bracket useEffect hook in the parent component that uses this unique identifier to do get request to "status" anytime the page loads to see if the client is logged in. If they are it can re-assigns it's user information to a useState variable. When the user wants to log out we can create a logout button with a onClick handler that does Delete request to status. The only question is what can we use to uniquely identify the client? Lets starts off with some quasi bad ideas before we get to the good idea!

## Using IP Address as a Unique Identifier 

Well every networked device has a globally unique M.A.C address so when it comes to finding a truly unique Key then you can't do much better than this. But no JavaScript is too high a language for it to gain access to something like this. But perhaps something similar might work, like an I.P address? 

The problem with this is that multiple users on the same network can share the same I.P. address. So it can't guarantee that we'd be able to uniquely identify all of our users. Which could mean that our site could mistakenly give User B access to User A's credentials if they share the same I.P address. So its safe to say this would be a bad idea! But since this is more of a fun thought experiment. Let's proceed!

The first question we want to ask is if we can't pull a M.A.C address from the client's system using javascript then how do we pull their I.P. Address? The answer to this is you can't! But you can write javascript that sends a fetch request to a free api that will tell you what your I.P. Address is. Personally I recommend using:
https://api.ipify.org?format=json

Now by implementing a simple fetch request within an empty bracket useEffects hook, we can pull the clients IP address anytime they refresh or load the app and save it to a useState variable! Now that we have our unique identifier we can use it to do a fetch to localhost:3000/status to see if the user is logged in anytime the window is opened or refreshed! And if we added other key/value pairs associated with the clients browser such as "screen.width" we could help prevent situations where two people on the same I.P. address access the site. But even this wouldn't eliminate all the situations. So lets see if their isn't a better way to do this.

## Local Storage

Yep, now we get to the real solution, Local Storage! What is Local storage? It's exactly what it sounds like, data that your browser stores locally. And unlike session storage, that your browser immediately erases anytime the window is closed, local storage will persist until the client chooses to erase it. We can access local storage with javascript by using window.localStorage and then calling its methods setItem(), getItem(), removeItem(). Now when the user logs in you can have them generate a random unique identifier key and use it as the id in your POST request to "status" and then place it into their localStorage with setItem(user, identifierKey). Now we use getItem(user) inside an empty bracket useEffect followed by a get request to "status" and we've got a persistent login. All in all this isn't too different from what most websites do with cookies.