Hey, guys.
In this lesson, we're going to be learning all about API authentication and authorization, the ability
to prove that you have the rights to access a particular API.
Previously, we saw that we were able to make very simple GET requests using Axios, or coming from our
server side and also doing it via Postman,
but you can imagine that there are a lot of scenarios where maybe you don't want everybody to be able
to access your API.
Let's say that the data that you hold behind your API is a resource, right?
Let's view it as money because after all, in our current day and age, data is extremely valuable.
In that case, let's imagine that we have our data locked up in a vault like a bank does, and our API
is the front desk where we can take and handle requests from customers and clients.
So let's say somebody bad comes along and says, "Well, I'd like to get Â£100, please" using the API,
and they try to get hold of some resource.
Now so far this works with everything that we've seen,
our API would say, "Well, here you go. Here's the money that you requested," and off he goes.
What we want instead is in certain scenarios we want to be able to protect the resources behind our
API by using authentication.
So how does that work?
Well, in that case, we need to know who are you when you're making these requests?
And depending on whether if you have the authentication or not, then we might say, "Oh 401, (Unauthorized).
Sorry, you can't do that."
In this lesson, we're going to be learning exactly how we can authenticate the user or the client that
is making the API request and depending on whether or not they are authorized to make that request,
we can send them the data or tell them, "No, sorry, that's not allowed."
In terms of authentication, I like to think of it as four tiers.
There is the Zero Authentication, so none at all,
and that's what we've been working with so far.
There is Basic Authentication, API Key-based Authorization and also Token-based Authentication.
Now I'm going to tell you a little bit later on what's the difference between authentication and authorization.
Let's first go in order of security and let's start with the first type, No Authentication.
Now we've already seen APIs with no authentication.
For example, when we worked with the Bored API, none of the endpoints in the API required any sort
of authentication.
So what can an API do to prevent abuse of the API?
Let's say somebody makes way too many requests and there's no way to check who they are or where they're
coming from,
then the way the API providers might add a safety check is to put in a Rate Limit.
As you saw in the bored APIs instance, we had a rate limit of 100 requests per 15 minutes and I put
in that rate limit so that under most cases as a student, that should be enough for you to work with
the API, and get hold of the data and try out the things you want to try, without hitting it up too much
and then ending up making the API go down for everyone.
So this is one way.
So you can check each IP address, how many requests they're making per minute and based on some sort
of arbitrary decision that you make, you can say, "Well, I'm going to limit it to this amount."
So that's something that you commonly see with public APIs that have no authentication and no authentication
is great because it means it's super inclusive,
anyone can use it,
it's super easy to get started and usually, if you don't have changing data that you're protecting or
data that needs to be assigned to a particular user, you very often see no authentication APIs.
If you go back to the Bored API Documentation, you'll see that all of the endpoints don't require any
sort of authentication and you can simply just make the request as anyone and you'll be able to get
the data back.
But the API requests are in fact rate limited and that means that we do have some safety measures,
although it is not a measure to authenticate or authorize any sort of API user.
Let's move on to the next level of security, Basic Authentication.
And as the name suggests, it is pretty basic.
So how does it work?
Well, you provide a username and password when you make your API request.
What that means
is you are authenticating yourself to the API provider.
You have an account with the API provider,
by providing these two pieces of information, you are proving your identity.
Usually, the way that Basic Authentication is done is by passing over a Base64 encoded string in the
header of the request.
Now, what is Base64 encoding?
Well, it's basically taking text which is ASCII,
so anything that you can type on your keyboard and that can be converted into bits.
So zeros and ones to represent that particular character.
And then we can take the bits and then encode it into another character.
Now usually when we do Base64 encoding, there is a little bit of expansion,
so for example, by starting with the word man, M-A-N, the end result that we get once we've done our
Base64 encoding is TWFU and you can see we've got one more character than previously.
And depending on whether if you have spacing in your line of source encoding, then you might see extra
characters as well.
Each character is represented in binary, and I've seen some people who can actually read binary, which
I think is a crazy skill, but probably not that useful because computers can do it faster.
After all, this is basically computer language, right?
When we first started out with computers, we had a button for on and we had a button for off.
And by switching things on and off, on and off, we could represent to the computer what it is that
we wanted to type out or what we wanted it to number crunch and do all of the computations and all of
the things that computers do through these zeros and ones or these on and offs.
As you can see, each character that you can think of is represented in binary.
And then by taking that binary and passing it through a special encoding method, we end up with Base64.
And then we simply format it in this format,
so the username: password,
and we convert all of this into Base64.
So you'll end up with some sort of long string full of characters that represents this data
but in Base64.
And then what you can do is you can add this to an Authorization header and you can pass this data along
when you make your requests.
Let's see how this works in practice by trialing it through Postman.
The API that we're going to be using is another one of our own APIs and it's called the Secrets API.
So this API is all about putting your confessions into a database and for people to be able to share
and view each other's secrets anonymously.
The API has different endpoints with different levels of authentication.
What we can do with this API is we can register a new user by passing over a username and password in
the body of the POST request.
And once we've registered ourselves on the service then we can use that username and password to perform
a request using Basic authentication.
The way that our endpoints on this REST API works is if you wanted to get a random secret from the database
of secrets, then you don't need to authenticate yourself because we're sending over a small piece of
data,
people are probably not going to hit up this route too often, but if you want something a little bit
more involved, a little bit larger in terms of size of the response and also a little bit more precious
in terms of our resources, then we have a gate.
So we use basic authentication to make sure that at least you are a registered user,
and if down the line, we want to make sure that we check which users are making lots of requests,
say you want to have a paid tier for your API, all of that kind of stuff is possible.
So let's make a request to this endpoint using Basic authentication and Postman.
So I've got Postman up here on the right and I'm making an HTTP GET request and the URL that I'm going
to hit up is this particular URL.
This is the base URL for our API, secrets-api.appbrewery.com and I encourage you to read through the Docs as
always before you make any sort of request to an API.
And what this API has is it has a Query Parameter called "page," because when you get hold of all pieces
of data, say all the secrets on the database, it's going to be a lot of data and we don't want to
send massive amounts of data over the Internet when people are making API requests.
So normally what people do, these API providers, is they can paginate the response, so they'll give
you 10 at a time or 20 at a time and you can request which page you want, maybe you'll request
Page 1,
and then once you've dealt with the data there, you can request Page 2 and so on and so forth.
This is simply one of the parameters that we can add into the query parameter to determine the type
of response we get back.
The important thing now is authorization or authentication.
And the type that we want to use is the Basic Authentication.
We have to type in a username and a password in order for this to work.
What I want you to do is to go ahead and use this endpoint POST/register to register yourself
a username and password, and then once that's done, go ahead and use that username and password to hit
up the /all route.
Pause the video here and give that a go.
All right.
So let's run through this.
The first step is to make a POST request to the register route.
Let's go ahead and hit up the correct endpoint and then we're going to pass over some Body parameters
in the format of form-urlencoded.
And we have two Keys, a username and a password.
And I'm just going to put in a random user, let's say our jackbauer user.
Let's say Jack Bauer wants to use our API and he wants to confess to some of his deepest, darkest secrets.
So I'm going to type a password and then I'm going to go ahead and hit Send to make this request.
And hopefully, you'll see down here in the responses that we get a, "Status: 200", which means everything
went A-OK and that I am now successfully registered.
Keep a hold of your username and password because we're going to need it in our Basic authentication
to try and request all of the secrets. We've got, our type of authorization selected as, Basic Auth,
and then I'm going to type in my username and password.
Once I've got both of those pieces of data, hit Send and you'll be able to see that we've got our secrets
coming back, ten per page.
Now, I wanted to mention that when we're using Basic Authentication using Postman, it's actually doing
some magical stuff behind the scenes
for us. What it's doing is it's generating the authorization header automatically based on the username
and password that you've provided here.
So you can see this if you go over to the Headers tab and you can see they've automatically generated
this header with a key of authorization and a value of Basic with the B capitalized space and then a
string that represents your username and password.
Now I can prove this to you if you go ahead and copy your own string that you have in Postman that's
generated here and go to a website called base64decode.org and paste that string into the top box,
hit Decode and you can see it automatically decoded it to the original format, which is username :
password.
And that is basically what's happening behind the scenes here.
So when you're making server-side requests that need basic authentication or authorization, you can
also do this yourself,
create the headers, use this as a string, convert your username and password, add in the word Basic
and add this as a header.
But in most cases, if you're using a library like Axios, it'll be able to generate all of that for
you by providing your username and password.
All right.
So did you manage to get this to work?
Did you manage to use Basic Authentication to authenticate yourself with the API provider and get hold
of some secrets?
Like, "I talked to my pet fish and imagine they're responding to me with witty comebacks."
"Uh, we've all been there."
We've now seen No authentication and Basic authentication in action when it comes to APIs.
Now, let's go ahead and take a look at API Key Authorization.
One thing you'll notice is that this term authorization, if you're in the US, that's spelled with
a Z, but I'm in the UK, so it's spelt with an S, authorization versus authentication.
What is the difference?
Because you hear it a lot and you're often wondering, well, am I using authorization or am I using
authentication?
So the difference between these two forms is if you have a user, they can authenticate themselves with
your service.
That means you are logging in or you are registering.
But authorization is simply a client who is allowed to use your service with an API key that might be
associated with a user, in which case they are authenticating themselves and then getting an API key
to authorize themselves to use your API.
But it could just be you don't even need to register with the API provider and you can simply get hold
of an API key and authorize yourself with the API provider.
That is the difference.
Authorization is something that allows you to use an API.
Authentication is something that allows you to be identified as a user to the API provider.
You'll see that a lot of public APIs use API keys and it's really useful because you can then track
the usage per API key.
So for example, if you signed up for the Google Maps API, you can use all sorts of different APIs
that they provide, for example, the Places API to find all the different things that show up on Google
Maps,
or you can use the Distance Matrix to calculate the distance between two points in time, again, using
Google's APIs.
And every single time when you make a request, you need to use this key before you can get back a response,
then they can log, well, how many requests are you making with that key?
So you can see in this case they're using the places API 200,000 times per day.
So you're making 200,000 requests per day.
And as with most public APIs, they have to stand up their own infrastructure, their own servers,
they have to maintain these server computers, etcetera.
There's a lot of costs involved, so it's often that they will charge you for using their APIs.
For example, in this case, this person is racking up $2,000 worth of API usage and by looking at how
often you're needing to make requests through your API key, they can determine how much they should
charge you.
This is useful to know both as an API user as well as an API provider and in future lessons we'll see
how we can create our own APIs and we'll look at the other side of the coin.
But for now let's focus on the client-side.
The easier side for now, if you go back to our Secrets API documentation, you can see that we have
some endpoints that require an API to authorize your usage and in order to get hold of an API, there
is the generate API key endpoint, which for now we've kept it pretty simple.
Just allows you to hit up this route, make a GET request and get your own API key to use.
And once you've generated the API key you can scroll down to the filter endpoint.
This endpoint allows you to return some secrets with a particular embarrassment score, so you'll see
that each of the secrets are associated with embarrassment scores or the emScore.
And this is just a way for the user to provide a piece of metadata about,
on a scale of 1 to 10, how embarrassing is your secret?
And by using this filter endpoint, we can provide this score as a query parameter and then we can provide
a number to say what is the minimum embarrassment score to filter for?
But most importantly, in order for this request to pass, we also need to pass the API key as a query
parameter.
And this is the key that we generated previously from this step, generate-api-key.
So I want you to pause the video and give this a go using the
documentation from secrets-api.appbrewery.com. I want you to use Postman to get hold of all the embarrassing
secrets that have an embarrassment score of seven or more.
So pause the video.
Give this a go.
All right.
So the first step we need to do is we need to generate an API key.
So we would go on to the website.
Maybe we would give our card details, maybe we would need to sign up and log in,
but either way, at some point we will hit up this endpoint and get the API to give us an access key.
Once we've gotten hold of the access key, then we can go and hit up the routes that require it. In the
Secrets API,
that is the filter endpoint,
we can make our requests to this endpoint,
/filter and we can add the parameter which is called score that tells the API what is the
minimum score
we want to filter by and I'm setting that to 7.
Coming into Authorization, we can provide our API key here where we say what is the Key and what is
the Value.
The key here is apiKey, spelt with a capital K, as you can see in the Docs and our value, I'm just
going to paste in from the point where we got it from and we're going to add it to the Query Parameters.
With API keys,
sometimes the API requires you to add it to the Header of the request and other times it requires you
to add it to the Query Parameter.
It depends on the API and you should always read through their Docs to figure out what you need to do.
So now we're ready to go ahead and hit Send.
And once you've done that, hopefully you've got a correct key, then you should get back some secrets
that are all filtered by the emScore.
So let's see, what are some of these embarrassing secrets?
"I have a secret collection of embarrassing childhood photos that I use to blackmail my siblings."
Pretty useful, sibling blackmailer.
All right, so now let's look at the final form of authentication that we want to cover, which is Token
Based Authentication.
Why is it that we're increasing in levels of security?
Well, no authentication is obvious, but Basic Authentication uses a username and password that's passed
over as a Base64 encoded string in the header.
As you saw, I was quite easily able to use the Base64 decoder to get back in clear text the username
and password.
Now that means it's equally possible for somebody on the internet to intercept your API requests and
to be able to do the same.
So why do we still use it?
Well, most API providers that use Basic Authentication will have HTTPS on their domain, which means
that we're using cryptography to securely encode all the data that being passed back and forth.
And even if somebody intercepts the packets, they won't be viewing the string as what we saw,
instead, it will be mumbo jumbo that they cannot decode.
But nonetheless it is still passing username and password,
and if it's a less secure website or there is something that goes wrong, then there is a risk there.
Now, API Key Authorization is a little bit more secure because nowhere do we actually type in our username
and password,
instead we have this API key which can be deleted and regenerated.
It can have caps on it, so you can rate limit it.
You can say, "I'm generating this key, but I only want to make say a thousand requests a month, so I'm
only paying for that amount."
So even if somebody intercepts this API key, they won't be able to get hold of the username and password.
They won't have any of your payment details.
It is just a reusable code that you're using to access an API.
Finally, the Token-Based Authorization or authentication is even more secure because essentially we're
getting the user to use a username and password to log in and then once they've logged in, we generate
a token to be used with the API so the API doesn't get involved with the username and password and instead
it's the token that's constantly being used to interact with the API.
Normally you'll see Token Based Authentication as OAuth and OAuth 2.0 is probably the industry standard
for doing token-based authentication.
And this is kind of what happens behind the scenes.
You have a user for a service and you want to be able to act on their behalf, so you get them to sign
in with their username and password on the API provider's website and then
the API provider generates a token off the back of that.
And then this token can be passed back to you as the third party and you can use this token to interact
with the API.
So let's see this as a real life example.
So let's say that you are building a third party app, say it's a weather app, but you have a special
twist on the app where you are going to get hold of a user's events in their Google calendar.
So you want to see that they have a meeting, for example, on Tuesday and it's happening in Baltimore.
So you grab all of these pieces of data and you look at the weather for that location and that date,
and maybe you would be able to send the user an alert to tell them to bring an umbrella to that particular
event.
That's the idea behind interacting with the Google Calendar APIs. For the user to be able to grant you
access to this data,
well, what do you have to do? If you weren't using token-based authentication, then you would have to
give us, this third party, the username and password, so that we can use this to interact with the
Google calendar API.
Instead, what we're able to do is we can use token-based authentication or OAuth to get the user to
sign in with Google, and this generates a token for us to get hold of and then we can use this token
to interact with the Google Calendar API. And then we can get hold of the user's events, their meetings,
we can even post data or delete data,
we can basically interact with Google calendar as this user without ever needing to get hold of their
username and password.
And instead all of that security stuff is handled by Google.
So this is a way more secure way of doing API authentication.
And every time you've seen this screen where it's asking you to authorize a particular app on the behalf
of your Google account, then you have performed this process.
But let's see it more concretely using our API.
If you take a look inside the Secrets API, you'll see that there is a path that allows us to get hold
of secrets based on the ID of the secret.
This path is protected by Bearer Token Authentication and Bearer Token Authentication uses a user's
username and password to authenticate themselves on our server, and then our server generates a token
that will be used as a proxy for anybody else to interact with the API as that user. We can use the
get-auth-token path by posting a request with a body of username and password.
Once the server has successfully authenticated that user, then they will pass back a token and we can
use that token then to interact with the rest of the API.
And you'll see this very commonly when you want to say post something on behalf of a user or change
something or delete something on behalf of a user, you're basically interacting with a service as if
you were the user,
but because we're using token-based authentication, you never need to get hold of their username and
password and we can keep all of that secure.
Let's give this a go.
Open up Postman and see if you can figure out how to get hold of the secrets using this endpoint and
get hold of the secret with an ID of 2.
Pause the video.
Give this a go.
All right.
So first we need to use this get-auth-token path in order to get an authentication token and we're going
to make a POST request to this path.
So let's change that.
And we want to add in, into the Body, some form-url encoded data and we want to pass it over our username
and also our password.
I'm just using the username and password that I got hold of earlier when I registered myself and I'm
going to pass in the values.
And then I'm going to go ahead and hit Send.
If you're doing this for the first time, you'll see your token being generated.
If you're doing this for the second time, you're still getting the same token.
But it's telling you that you have already been issued a token and it's just reminding you of what it
is.
Both options could happen, but once we've gotten hold of our token, then we can use it to get hold
of a secret with a particular ID.
Let's go ahead and copy the endpoint and I'm going to change this url parameter to get hold of the secret
with an ID of 2.
So now, before I can send it, I need to change the authorization to a Bearer Token Authorization and
I'm going to paste in the token that I got back from the previous step in here.
And just like what it did with basic authentication, Postman is generating an authorization header
behind the scenes
automatically based on the token that you put in here.
And you can see this by going to the Headers, you can see that it's generated a Header with key of
authorization and value of Bearer, and then the token that you have added in here.
If you're doing this by yourself using just code, then this would be the full value of that header
that you're sending over with your request.
So now let's go ahead and hit Send and hopefully if everything worked, we'll get back the secret with
an ID of 2.
Now, it's time to try an exercise and do everything that we did just now, exploring the different ways
of authenticating yourself or authorizing yourself with an API,
but instead, this time we're going to do it with code.
Go ahead and download the starting files 5.4 API Auth.zip extract the zip and open it up inside VS Code.
Once you're here, the first thing I want you to do is to cd over to the API Authentication folder and
then I want you to do your usual thing where you use "npm i" to install all the required node modules.
And then I want you to go to solution.js without scrolling down, without looking at the solution.
I want you to update all of these constants using yourUsername, yourPassword, yourAPIKey,
yourBearerToken that you generated earlier when we were going through each of the steps in Postman.
And once you've done that, then I want you to use Nodemon to run the solution.js and then we can
head over to localhost:3000 and you'll see this basic website.
Now, what we're able to do here is we can hit on each of these different authentication buttons.
No Authentication gives us a random secret. Basic Authentication
will hit up the GET/all path.
The API Key Authentication will get us the filtered endpoint and Bearer Token Authentication will get
us a secret with a particular ID. So you can see we're using all of the same endpoints that we did using
Postman, but this time we're actually hitting it up from our server, so we're doing these server-side requests
using Axios, but we're also making sure that we learn how to do that using all of the different types
of authentication.
Take a look inside the index.js and I have a bunch of TODOs for you to be able to work through this
and you might need to remind yourself of how to make requests using Axios and you might need to use
some of the hints that are available in each of the steps,
but essentially, you should be able to complete this server-side code so that it works the same as the
solution.js
Pause
the video now and give this a go.
All right.
So how did you get on with that?
Let's go through the solution code and see if you managed to get it to work.
The first step is to fill in all the values that you had from the three different types of auth,
and once you've done that, we're going to use each of these constants in the different types of authentication.
So the first one we're going to do is actually the route that has no authentication.
So we're using a "try, catch" block and we're using Axios to make a GET request to our API URL at the random
endpoint.
This is pretty simple.
And then once we get back the data, we pass it over to the i ndex.ejs and we use JSON Stringify to pass
it over just as a simple string instead of a JavaScript object.
This content is then caught in the index.ejs and displayed in this box right here.
This is just to whet our appetite and get us started,
the next one uses Basic Authentication and if you got stuck on how to do this, as always, there is
Google out there as your friend.
But even better than Google is me as your friend because I've actually provided this hint to show you
how you could have searched to find this particular StackOverflow question, which is, "How do you send
Basic Authentication with Axios?"
That's pretty much what we want to do here.
Right?
And it tells us that there is an auth parameter that we can add to our requests by adding in a username
and password.
What we're able to do is we can provide this auth after we've provided the endpoint and we can add in
our username or password under this parameter name of auth and it will do all of that Base64 encoding
for us and then we can send over this request and we should be able to get back our data, which again
we turn into a string and send over to the front-end.
Now, the next one uses the API key,
and remember in our case, the API key is also sent over as a parameter.
With Axios, we can send parameters like this.
Alternatively, we can simply add them onto the end of our URL.
Both ways are correct.
It really depends on which one you want to use,
and if you've searched around, or you looked at the Axios Docs, you might see something like this,
but you might also see other people add it straight into the endpoint.
It doesn't really matter whichever way you did as long as it worked.
We had to provide a parameter in the form of a score.
The embarrassment score that we want to filter on, and also our API key.
And once we get back the data again, we pass it over to the front-end.
Now the final one we have requires a Bearer Token.
So in this case we're hitting up the secrets endpoint and we're providing the ID of 2 to get hold
of that particular secret.
Now, I'm passing in the config so that I can provide a parameter for the headers parameter.
And in here I'm putting in the Authorization as the key and the value as the word Bearer with a capital
B, a space, and then the Bearer Token that we generated earlier on.
And again, I added a hint to maybe how you can figure this out, but essentially this is the config
and you can either add this object straight into here, as we did with our parameters or with our authentication,
or you can separate it out whichever way you prefer.
Then we make the GET request, we get back the data and we send it over to the front-end.
If you got stuck or something didn't work, make sure you review the solution.js code and fix your code
so that you get it to work.
You can also take the code and figure out where you went wrong and understand what it is you have to
do in order to get it to work.
But hopefully, you managed to try out all of the different forms of authentication using code and using
Postman.
In the next lesson, we're going to be using some of that authentication, but we're also going to be
exploring some of the other parts of this REST API.
So for all of that and more, I'll see you there.