Authentication is the process of verifying who a user is. If you don't have a secure authentication system, your back-end systems will be open to attack!
Imagine if I could make an HTTP request to the YouTube API and upload a video to your channel. YouTube's authentication system prevents this from happening by verifying that I am who I say I am.
Passwords are a common way to authenticate users. You know how they work: When a user signs up for a new account, they choose a password. When they log in, they enter their password again. The server will then compare the password they entered with the password that was stored in the database.
There are 2 really important things to consider when storing passwords:
We won't be writing code to validate password strength in this course, but you get the idea: you can enforce rules in your HTTP handlers to make sure passwords are of a certain length and complexity.
On the other hand, we will be writing code to store passwords in a way that prevents them from being read by anyone who gets access to your database. This is called hashing. Hashing is a one-way function. It takes a string as input and produces a string as output. The output string is called a hash.
We'll cover how hashing works in-depth in a later course. For now, just know that hashing is a way to store passwords in a way that prevents them from being read by anyone who gets access to your database, but still allows us to compare passwords when a user logs in.
For the password hash, we will use Argon2. To help with this, use the library argon2id, which is a convenience wrapper around Argon2.
Download the library:
go get github.com/alexedwards/argon2id
I wrote a couple of simple unit tests to ensure the package is working as expected.
{
"password": "04234",
"email": "[email protected]"
}
As long as your server uses HTTPS in production, it's safe to send raw passwords in HTTP requests, because the entire request is encrypted.
Use your internal package's HashPassword function to hash the password before storing it in the database. Do NOT return the hashed password in the response. Again, that would be a security risk.
{
"password": "04234",
"email": "[email protected]"
}
You'll need a new query to look up a user by their email address (you don't have access to an ID here). Once you have the user, check to see if their password matches the stored hash using your internal package. If either the user lookup or the password comparison errors, just return a 401 Unauthorized response with the message "Incorrect email or password".
If the passwords match, return a 200 OK response and a copy of the user resource (without the password of course):
{
"id": "f0f87ec2-a8b5-48cc-b66a-a85ce7c7b862",
"created_at": "2021-07-07T00:00:00Z",
"updated_at": "2021-07-07T00:00:00Z",
"email": "[email protected]"
}
Run and submit the CLI tests.