20
The Basic Necessities of a Mock User Authentication with json-server-auth
When first building a react app as a beginner, you may have all these cool ideas you want to include in your project, but the one thing holding you back is a user authentication system where you can store the information of different users to your app. Maybe you want to hone your skills on the front-end and just don't have the resources to build out an extensive back-end to handle this. Here, we will walk through the BARE MINIMUM of what you need to do to mock this functionality.
Our example will be making use of the json-server and json-server-auth libraries to make all the magic happen. Using both in tandem will allow us to prototype and mock our front-end application with an authentication like system. These libraries will make use of a local JSON file to store all of the data as if we were making a request to a server. Instead, json-server will watch our database JSON file to retrieve that information fully on the client side.
To install json-server and json-server-auth in your project run the corresponding command depending on which package manager you are using for your react app:
# NPM
npm install -D json-server json-server-auth
# Yarn
yarn add -D json-server json-server-auth
Make sure to include a JSON file where you want to store your data (we'll call this db.json) and give it a collection. The name of that collection is important, and has to be named 'register', 'signup', or 'users'. When you are making a POST request, json-server-auth will look for these to route correctly. For our example we will use 'users'.
{
"users": []
}
Now you are set up to create any sign up and log in forms necessary to be able to manage users! To run our react app with json-server auth, run the following command in one terminal:
json-server --watch db.json -m ./node_modules/json-server-auth
Then you may start your react app with the appropriate command:
#NPM
npm start
#YARN
yarn start
Going through the flow of a new user, we will first want to sign up component that will be shown on our front end. Here we have set up a controlled form that will be used to collect our new user information and on submit, will create the new user in our database.
import { useState } from "react"
function Signup() {
const [formData, setFormData] = useState({
email: '', // required
password: '', // required
username: '' // optional
})
function handleSubmit(e) {
e.preventDefault()
fetch('http://localhost:3000/users', {
method: 'POST',
headers: {'Content-Type' : 'application/json'},
body: JSON.stringify(formData)
})
.then(res => res.json())
.then(data => console.log(data))
}
function handleChange(e) {
setFormData({...formData, [e.target.name] : e.target.value})
}
return (
<div>
<h1>Signup Form</h1>
<form className='login-form' onSubmit={e => handleSubmit(e)}>
<input type='text' placeholder='Username' value={formData.username} name='username' onChange={e => handleChange(e)} ></input>
<input type='text' placeholder='Email' value={formData.email} name='email' onChange={e => handleChange(e)} ></input>
<input type='text' placeholder='Password' value={formData.password} name='password' onChange={e => handleChange(e)} ></input>
<button className='login-btn' type='submit'>Sign Up</button>
</form>
</div>
)
}
export default Signup
Looking at our handleSubmit function, we'll want to make a POST request to /users of where our localhost server is running. The formData body that we are giving that request MUST include at least 'email' and 'password', while all other keys can be optional for additional user information.
Next for our login component we can define as follows:
import { useState } from "react"
function Login() {
const [formData, setFormData] = useState({
email: '', // required
password: '' // required
})
function handleSubmit(e) {
e.preventDefault()
fetch('http://localhost:3000/login', {
method: 'POST',
headers: {'Content-Type' : 'application/json'},
body: JSON.stringify(formData)
})
.then(res => res.json())
.then(data => console.log(data.user))
}
function handleChange(e) {
setFormData({...formData, [e.target.name] : e.target.value})
}
return (
<div>
<h1>Login Form</h1>
<form className='login-form' onSubmit={e => handleSubmit(e)}>
<input type='text' placeholder='Email' value={formData.email} name='email' onChange={e => handleChange(e)} ></input>
<input type='text' placeholder='Password' value={formData.password} name='password' onChange={e => handleChange(e)} ></input>
<button className='login-btn' type='submit'>Login</button>
</form>
</div>
)
}
export default Login
We have a very similar POST request to our sign up form, however this time we are only looking for the user's email and password in order to authenticate existing users in our database. Also note we are posting to /login in this instance even though we do not explicitly create a login collection.
You will want to style your form components to your liking and perhaps have proper routing to the corresponding pages in your app, but for simplicity we will render them on one page to demonstrate json-server-auth. Rendering our components to the DOM we now have:
Our user can then input information to sign up and once submitted, will post to our db.json file our new user:
{
"users": [
{
"email": "[email protected]",
"password": "$2a$10$TGpBQYJF6bQFEipnwaaoiuCRVht/.jAyrOYQnq8Xz5CvXYNu6O2LO",
"username": "myusername",
"id": 1
}
]
}
Notice that json-server-auth has encrypted the user's password, but once we log in with the appropriate data, we will be able to access the contents of that user object. Once our user submits their log in form, we can access their data from our fetch's response. In our log in component above we log data.user and that gives us the following:
From this data we can access the username, email, and an id given to our user.
On a larger scale for your applications, you will probably make use of more optional fields when it comes to creating your user's information. However, once you are able to handle the user's log in, the sky is the limit to what you can do with their data. This will work at a basic level with just an email and password, but if you wish to read more about json-server-auth and some of it's further capabilities with tokens or authorization flow you can find its documentation here.
20