Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
Implement Sign in form. Use Basic Authentication to call a GET request from the api. If user is authenticated they will be navigated to /authenticated
route.
Resources
- The Authorization request header – MDN
- Base64 encoding and decoding - MDN
- btoa() – MDN
- fetch() - MDN
- useNavigate - React Router
- useRef - React
- .json() - MDN
Treehouse Courses and Workshops
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
Now that we're successfully
registering a new user,
0:00
let's keep it going by
authenticating the user.
0:03
In this video, we'll implement
an authorization request header and
0:06
the basic authentication scheme to
authenticate a registered user.
0:10
That way the user can use their
credentials to sign into the app.
0:15
Open up the UserSignIn component.
0:20
When the user submits the sign in form,
0:24
we'll need to send the credentials
to the server in a fetch request, so
0:26
that the server can return to
us the user's information.
0:30
We'll start off by tagging
the handleSubmit function with the async
0:35
keyword,
0:39
and then create the fetchOptions object.
0:40
For this fetch request,
we want to get the user's info.
0:44
So we'll set method to GET.
0:49
In the basic authentication scheme,
a server requests
0:53
authentication information,
a user ID and password from the client.
0:57
The client passes the authentication
information to the server and
1:02
an authorization header
using Base 64 encoding.
1:07
Let's start by encoding
the user's credentials,
1:11
then adding them to the request header.
1:15
Above fetchOptions we'll create
a credentials object that will hold
1:17
the username and
password the user provides.
1:22
We'll set username to the current value
of the ref with username.current.value,
1:26
and for password we'll set it
equal to password.current.value.
1:33
We'll store the encoded credentials in
a variable called encodedCredentials,
1:42
and set it equal to the btoa method.
1:48
The btoa method creates a base 64 encoded
ASCII string from a string of data.
1:52
So we'll need to pass btoa,
a string that contains the username and
2:01
password credentials.
2:06
Pass btoa a template
literal that interpolates
2:08
the username with credentials.username and
2:13
password with credentials.password.
2:17
Basic authentication requires the username
and password to be separated by a colon.
2:21
So be sure to include
the colon in between.
2:27
Back in fetchOptions,
we'll add a property called headers and
2:31
set it equal to an object.
2:35
Credentials need to be passed
in an authorization header.
2:39
So add the Authorization property
inside the headers object.
2:42
Using a template literal, we'll set the
authorization type to basic, since we're
2:48
using the basic authentication scheme,
followed by the encoded credentials.
2:53
All right, our fetch options is all set.
3:00
Let's now call the fetch method.
3:03
We'll store the response in a variable
called response and set it equal to fetch().
3:05
And don't forget to add the await keyword
in front of fetch since it returns
3:12
a promise.
3:16
For this project, the API uses
the same URL we used to add a new
3:18
user to also get a user's information.
3:23
So we'll copy the URL and
back in the user sign in component,
3:27
we'll paste it inside our fetch method.
3:31
The last argument we'll pass the fetch
is our fetchOptions object.
3:35
We'll test our fetch method by
logging the response to the console.
3:40
Make sure to save our changes
then head on over to the browser.
3:46
We'll first need to fill
out the sign up form.
3:51
Once we've successfully signed up,
we'll navigate to the sign in route.
3:57
We'll use the same username and password
we entered in the sign up form and
4:02
click sign in.
4:07
Awesome.
4:09
We know our fetch method is working
because our response status code is 200,
4:09
which stands for OK.
4:14
Let's refresh the page and
submit an empty sign in form.
4:17
And we get back the status code of 401,
unauthorized.
4:21
All right, let's write our if / else
statements to handle the different
4:26
responses we get from the server.
4:30
Since I know we'll eventually have to
deal with errors, let's create the try
4:33
catch block now and move our fetch
method inside the try block.
4:37
Our first if statement will check
if the response status is 200.
4:43
If so, we'll store the user's
info in a variable called user.
4:49
To get access to the user's
info from response,
4:56
we'll need to parse response's body
text to JSON with await response.json().
5:00
We'll log user to the console to see
exactly what the server sent back.
5:07
Let's save our changes and
head on over to the browser.
5:13
We'll sign in again,
5:17
and in the console, we see the server
returned to us my name and username.
5:21
Great.
Back in our if statement,
5:27
we'll log to the console a success message
saying that the user has been signed in.
5:29
We'll use template literals so
5:37
that we're able to display the user's
username, and type success.
5:39
User.username is now signed in.
5:43
Once they sign in, we'll navigate
them to the authenticated route.
5:47
To do that, we'll need to use
React Router's useNavigate hook.
5:53
At the top of the file, we'll import
useNavigate by adding it next to Link.
5:58
Under the useContext hook,
we'll call the useNavigate hook and
6:05
set it equal to navigate.
6:10
Now we can navigate the user to
the authenticated route after successfully
6:14
logging them in with navigate(),
6:18
and passing it /authenticated.
6:21
We'll check if the server responded
with a 401 unauthorized status
6:24
by adding an if statement that checks if
the response that is equal to 401.
6:30
When this happens, we'll let the user
know the sign in was unsuccessful
6:36
by displaying an error
above the sign in form.
6:41
To do that, we'll call setErrors and
6:45
pass it an array with a message
sign in was unsuccessful.
6:48
Lastly, we need to handle any errors that
don't have the status code of 200 or 401.
6:54
We'll add an else statement
that throws a new error with
7:01
throw new Error(). Our
catch block will handle the error.
7:06
We'll have catch log that error
to the console and navigate them
7:12
to the error route with navigate and
passing it /error.
7:17
Lastly, let's quickly implement the cancel
button before testing out our code.
7:24
In the handleCancel function,
7:29
let's navigate the user to the root
route when they click the cancel button.
7:31
All right, let's save our changes and
test them out in the browser.
7:36
We'll first click the cancel button and
it brings us to the root route.
7:41
Great.
7:45
Let's try submitting wrong credentials or
a blank form, and
7:46
we see the message sign
in was unsuccessful.
7:51
Now let's test out how
our code handles errors.
7:55
Open the terminal where our server is
running and stop it with CTRL+C.
7:58
When we click the sign in button,
we're navigated to the error route and
8:04
the console logs TypeError:
Failed to fetch.
8:08
Okay, let's start up our server
again with npm start and
8:12
lastly test out a successful sign in.
8:17
The API server we're working with clears
all its data each time it restarts.
8:21
So we'll need to sign back up again
before we're able to sign in.
8:27
Once we signed up, we'll head on over
to the sign in route and sign in.
8:33
Awesome, we were navigated to
the authenticated route and
8:39
the console shows us the message "SUCCESS!
8:43
laurac is now signed in!"
8:46
Great job so far.
8:49
You officially used the basic
authentication scheme.
8:51
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up