Implementing JWT Authentication in React Native
Now that we have some sample data, we're going to extend the functionality of our application so that it has the ability to communicate with the outside world. It's going to make outside API calls and then it's going to give us the ability to see if a user is who they say they are.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

Let's get into that now. If you look at the API dashboard, you can see that we have this endpoint.

large

What this endpoint is is it gives us the ability to pass in authentication parameters. In this case, it's gonna be an email address and a password and that is going to hit the DevCamp Space servers. If you're working on any other application, so say you're working for a client and they have an API, every API's gonna have some form of this type of functionality.

So what we're gonna do is we're gonna wrap up the email and the password, we're going to send that to the server and then from there, if the server verifies that that email and password are valid, so it looks it up in the database, and it authenticates the user, what it's gonna do is it's going to pass back what's called a JWT, which is pronounced "jot" token.

That token is what we're gonna be able to use in order to, for any part of our application, we're gonna be able to pass that back to the server and quickly see if the user's authenticated or not. If you've taken any of my other courses, and you've built out what was referenced as the HTTP-only cookie.

So if you went through the React Portfolio application, we used cookies in those examples and cookies are really nice because they actually allow us to skip this step. Cookies work automatically in a web browser and so you don't have to work with these tokens.

But on mobile devices, you can't use cookies. So that's the reason why we're using this authentication protocol and it's really the only option that you have to use.

So let's get started on this. The very first thing we're gonna do is we're gonna build out an API connector that calls this endpoint here and then we're gonna check to see if the user's authenticated or not. So I'm gonna copy this call right here and then let's open up Visual Studio Code and at the very top, so even above where it says export default, I'm gonna say const apiEndpoint and then just pass this in as a string.

AuthScreen.tsx

const apiEndpoint = "https://reactnative.devcamp.space/memipedia/memipedia_user_token";

The reason why I'm doing this, even outside the function, is because if you have any values, these are also called many times constants, if you have any constants or values that are not gonna change so they're not dynamic, then we are gonna be able to store them right here.

Eventually, we might change this up but for this video, it's gonna give us a nice way to wrap up this API endpoint. So we have that in place and now we need to import axios. So I'm gonna say import axios from axios and if you went through the documentation, and you researched it, then you should have a good idea of what axios does. In short, it gives us the ability to make API calls.

So we have axios, we have our apiEndpoint, we have our email address and we have our password values and those are gonna be used to be sent to the API and so with all of that in place, let's come down here and now we're gonna create a handler function.

So what we're gonna do is this process of communicating with the API, we're going to place all of that business logic inside of one function so that when a user presses Log In, then they are going to be make all of these things happen. It's gonna wrap up the email address and the password, it's gonna make the API call, it's gonna get back the JWT token, everything like that, so let's create that function.

So I'm gonna say const handleSubmit and this is gonna be a fat arrow function that will not take in any parameters and now inside of here, now let's make our API call so I'm gonna say axios.post and if you're curious on how I knew it was POST, any time you're working with API documentation, the endpoint is always gonna have one of four verbs. Right here we can see it says that this is gonna be a POST request.

large

So you're either gonna have POST, you're gonna have PATCH, you're gonna have DELETE, or you're gonna gave a GET. Those are your only four options and each one of them is a function on axios. So here I'm gonna say axios.post and then the very first argument, and you can see right here,

large

TypeScript is giving us some nice guidance, it says the first argument is a url which is a string, so that's our API endpoint. So here I can say apiEndpoint and then the next argument is gonna be any data. So this is where we're gonna be wrapping up that email address and password.

But instead of putting it directly in here, I'm actually gonna create a variable that I'm gonna store it in just because I don't like the lines of code to get too long because then they can get kind of hard to read and that's part of the reason why I created a variable for that long URL.

So now let's create a variable here, I'm just gonna call it params. You can call it whatever you'd like and params is gonna be an object. And inside of it, it's gonna have a nested object called auth. So A-U-T-H and this is something that is specific to the way this API is written, so you don't follow this every single time.

So every time that you work with JWT tokens, there may be some cases where your value's gonna be called auth, you may have others where it's not. That's why you have to always follow the API documentation. The developers that created the API have spent a lot of time writing the documentation with instructions on how to use it. For use, we're just gonna use this auth and that is where we're going to wrap up a object of email, which is going to map to email, and then password which is gonna map to password.

AuthScreen.tsx

const handleSubmit = () => {
  const params = {
    auth: {
      email: email,
      password: password
    }
  }
  axios.post(apiEndpoint)
}

So this set of params, it's just a basic object, just a normal JavaScript key-value pair object. The first key's gonna be auth and then we're passing in email and password. So now, with that in place, we can just copy params and then this is gonna be that second argument. As we go through this course, you're gonna see we're gonna eventually get to the point where we're passing in three arguments, but we're not gonna worry about that right now.

So we have axios.post, we're calling this endpoint and then we're passing in the email address and the password, so then we can say then.

AuthScreen.tsx

const handleSubmit = () => {
  const params = {
    auth: {
      email: email,
      password: password
    }
  }
  axios.post(apiEndpoint, params).then
}

and if you're curious on this or if your axios or your JavaScript promisees are a little bit rusty, the reason why we call then, and how you know it, is because axios.post, this function right here, it returns a promise. So if you go and reference the way promises work in JavaScript, a promise means that it is not passing back data.

So like many functions. So let's take, because this is a really important topic, we'll just take a quick aside here just to make sure this is 100% clear. Say that I created a function and I called this function sum and it took in two parameters. It took in say num1 and num2 and then it returned num1 plus num2. So what we're doing here, there you go, it'd probably help if I spelled it correctly, there you go.

So this sum function is taking in two parameters and then it's just returning a number. That's a very basic type of function. Well, the way axios.post works, it's not like that. It doesn't just return data, instead, it returns a promise. So you can't just go and say, in this case, grab the JWT token from what gets returned, we have to call then.

Any time you're working with promises, you have to call then in order to extract the data that got passed back. So lemme get rid of this sum example and so we're calling then and if you're wondering on how you can know that without just going through guides and tutorials, it's all in the axios documentation. That's the reason why I wanted you to go through that.

large

So I'm gonna say then and we're gonna take in the response. So this is the data that got sent back. And in this case, for this guide, we're just going to console.log it. So I'm gonna say console.log and say Response from handle submit, and then we'll say response.data and that's because every API response is the response contains a lot of data or a lot of information, the data's actually what we're wanting to pull.

AuthScreen.tsx

axios.post(apiEndpoint, params).then(response => {
  console.log("Response from handle submit", response.data)
})

So response is a object we're wanting to pull the data outside of that. So that's the first thing. And then we also want to see what would happen if an error occurred. So for that, instead of just saying then, we say catch. So catch is going to let us know if any errors happened. So we're, in this case, we're just going to do the same thing. We're gonna say console.log error getting token and let's just print out that error. If I hit Save, Prettier formats it nicely for me and now, we should be able to see it.

AuthScreen.tsx

axios
  .post(apiEndpoint, params)
  .then(response => {
    console.log("Response from handle submit", response.data)
  })
  .catch(error => {
    console.log("error getting token", error);
  });

The last thing we have to do is wire up this handleSubmit function to a button. So let's come down here and I'm going to create another TouchableOpacity link and so in this case, it's not going to have handleAuthTypePress, the function we're gonna pass in is handleSubmit and then for the text itself, we're gonna be able to reuse this header text here, so that's kind of cool.

So we're gonna be able to reuse this function because sometimes, we want the button 'cause that's what we're creating here. Sometimes we want the button to say Log In, other times we want it to say Register, so we can reuse that function.

AuthScreen.tsx

<TouchableOpacity onPress={handleAuthTypePress}>
  <Text style={{ color: "white" }}>{screenTypeText()}</Text>
</TouchableOpacity>

Let's hit Save and open up the simulator and then let's also open up the terminal. So the terminal, looks like everything looks like it's running properly. We don't have any errors. So let's type this in and make sure you're typing in exactly what you typed in to DevCamp space.

So for that, for me it was reactnative@devcamp.com and then I'll type in the password that I used. Now, if I click Login now, you'll see that that worked properly. So right here, this is the data the API sent back to us.

large

So the response is a jwt token and this is what a JWT looks like. So it's a long string of characters. It's broken up into a few segments by a period and this is what we're gonna store on the device. This is automatically generated from the server and then we're gonna store this on the device so in the future, any time that the user needs to prove that they are who they say they are, they're not gonna have to retype their login and password anymore.

Instead, we're just gonna store this and then we're gonna pass it up to the server and then the server's gonna be able to check and verify that the user is authenticated. So that is perfect.

Now let's try something else. So now type in the wrong password. Let's see what happens. So I'm gonna hit Login. And there you go. It says error getting token. The request failed with a status of 404.

large

The reason I wanted to show you that is because we're gonna have to take into account both of those options. We're gonna have to make sure that the user, if they get a JWT back, then we're gonna redirect them to the main part of the application where they can do everything like see posts, create posts, that kind of thing.

If they type in the wrong login information, then we need to let them know. So we need to do something like pop up an alert or do something like that so that they can fix whatever it was that they got wrong.

So all of this is working beautifully. We now have the ability to make API calls, we're connected to another server and now we're already performing authentication. Our users can get authenticated, we get our JWTs back and we're well on our way to a fully functioning application.

Resources