What is the difference between Authentication and Authorization?
Ever wondered what could be the difference between these two terminologies? Authentication and Authorization. This is exactly what I aim to cover in this part of my write-up. This first part of the write-up would look closely at the methods of authentication, and the second part would focus more on authorization.
If you have built an API that gives access to the outside world about certain pieces of data from your server, then it becomes necessary to determine who has access to what (authentication) and what actions are allowed (authorization) Figure 1 below.
The following methods for authenticating users' requests on an API endpoint would be discussed:
- HTTP authentication
- API key-based authentication
- Session/Cookie-based authentication
- JWT/Token-based authentication
Basic HTTP Authentication
The process of authentication checks whether a client and its user are who they say they are. With basic HTTP authentication (the simplest form of authentication), this is done via usernames and passwords. During basic HTTP authentication, the client provides a username and password (by way of the user) encoded within the header of the HTTP request it sends to your API. Your API then reads that username and password to check if the user is registered. This is achieved by checking if the username/password combination exists in its database, and, if so, authenticate the user and allow them to log in.
Advantages of basic HTTP authentication
The main advantage of basic HTTP authentication lies in its simplicity. It doesn’t require any extra storage mechanism for the username and password, as they’re transmitted from the client to the API directly in the HTTP header. From there, it’s a fairly straightforward process for your API to read these values and check them against its database of registered users.
Disadvantages of basic HTTP authentication
It’s risky to use HTTP authentication as a general authentication scheme (i.e., beyond an initial login request). As the username and password would be sent along with every request, the authentication details are more susceptible to being intercepted, and your application could potentially be exposed to harmful attacks, especially if the connection is insecure.
Thus, basic HTTP authentication is best kept for an initial login request only. Any requests after this can be authenticated using a different, more secure method.
Note:
There is a use case where it’s more appropriate to continue using HTTP authentication throughout an entire application, and that’s when an application will only be run on an internal network (or intranet). In this case, there’s no large risk of outside attack (the network isn’t accessible over the public internet), nor is speed of the essence, as the number of users accessing the app would be quite limited.
2. API Key-Based Authentication
The next form of authentication I’ll be looking into is key-based authentication. API key authentication is similar to basic HTTP authentication, except that it uses an API key (rather than a username and password) to verify a client’s identity. An API key is a unique piece of code assigned to a specific user (which, to reiterate, could be any individual whose identity persists between usages of the client application) and is usually a long string of characters looking something like this:
003026bbc133714df1834b8638bb496e-8f4b3d9a-e931-478d-a994-28a725159ab9
This API key is generated by the API the first time a client (and its user) registers with the app. Then, just like the username and password with basic HTTP authentication, the API key would be passed alongside every request from the client to the API. For example, say a curriculum team in an office wanted to use your image server to host images for their online course materials. They’d consistently be making requests to your API to upload new images. If you allowed the team to register for an API key, they could use (or create) an image uploading software that submits this API key automatically with every request to your API, thus authenticating every upload (Figure 2).
With API key-based authentication, the API key is transmitted within the request headers, similar to how usernames and passwords are transmitted in HTTP authentication.
While this is the most common way for an API key to be transmitted from a client to an API, there are a few other methods you may run into:
- Adding query strings to the URL endpoints themselves (e.g., a request made to the URL “apiname.com/movies&apikey=003026bbc133714df1834b8638bb496e-8f4b3d9a-e931–478d-a994–28a725159ab9”).
- Creating a custom header in an HTTP request
- Inserting into the body of the HTTP request
As you can see, basic HTTP authentication and API key-based authentication are very similar; the former uses a username and password for authentication, while the latter, an API key. Why would you use one over the other? Well, using an API key does bring with it a few additional benefits over basic HTTP authentication:
- An API key is harder to guess and, therefore, less likely to be intercepted; and
- It’s usually faster for your API to verify an API key than a username/password combination.
Limitations of API key-based authentication
Although API key-based authentication has some additional benefits over basic HTTP authentication, there are still a few limitations with this approach.
First, if a request containing the API key is intercepted by an attacker, the attacker will now have permanent access to your API. This is because API keys generally don’t expire or designate a specific time frame during which its sender (the user of the client application) is given access to your API.
Second (and similar to basic HTTP authentication), API keys typically give users of the API authorization to perform all operations within an application. (Remember that authentication refers to verifying clients’ identities, whereas authorization refers to controlling access to different parts of your application). While it would technically be possible to have different API keys receive authorization to different parts of your API, as mentioned earlier, this would be reinventing the wheel as there are better solutions involving JWT tokens and OAuth.
With those two methods out of the way, let’s take a look at an even better option.
3. Session/Cookie-Based Authentication
A cookie is a small piece of data created by a server and sent to your browser when you visit a website. Browsers often need to store and send it back to the server to tell it that the request is coming from the same browser, to keep the user authenticated.
As long as the user remains logged into the session, the client will send along the cookie with the session ID in every proceeding request to the server. The server compares the session ID of the cookie with the one it has stored in memory in order to authenticate the user’s identity and authorize their access.
Unlike the previous two approaches (basic HTTP authentication and API key), with a session-based approach, the session ID provided to the client will eventually expire — both on the server side (since a session won’t be saved in the server memory forever) and on the client-side (since cookies aren’t stored in the browser forever). Once the session ID of the user expires, the user would be logged out and no longer able to access their accounts without logging back in (and receiving a new session ID).
You’ve probably experienced this yourself. Have you ever cleared the cookies from your browser to find you’ve been logged out of your friend’s Netflix account? This process clears the session ID you would have stored for Netflix on the client-side. If you were to try and load the site again, you’d be logged out of the application and no longer able to make requests from Netflix’s client-side to Netflix’s server-side (to watch a movie, for example). This is because Netflix’s server-side would no longer be able to authenticate your identity via the cookie in your browser. If it can’t find your session ID, you’re out of luck (and will have to ask that friend for their password again)!
The simple fact that session IDs can expire makes session-based authentication safer than HTTP- or API key-based authentication. Even if an attacker were to intercept a request made with a session ID, they wouldn’t have permanent access to the application; thus, any damage would be limited.
Limitations of session/cookie-based authentication
This approach does come with its own limits, however, especially on the server side. As the server has to store a separate session ID for each client (including information about what that client should have access to), and additionally cross-check that session ID every time the client makes a request, coding, processing, and response times could suffer.
4. JWT (Token-Based) Authentication
JWT — JSON Web Token — is a JSON-based standard for creating web tokens that can be used for authentication (and authorization). Because it addresses some of the flaws already mentioned in the previous approaches, it’s become the de facto standard for most modern web applications. Before we explore how it avoids those flaws, let’s take a look at the flow of JWT authentication to see how it works.
With JWT authentication, the client makes a request to the server-side of an application, after which the server generates a web token that represents an encoded version of some claim — for instance, the client’s identity, what the client should have access to, and for what length of time they should be allowed access to it — and sends this token back to the client. The client stores this JWT and sends it alongside every subsequent request to the API, where the server then validates it in order to verify the client’s identity and process its requests.
The “header” component contains information about the type of token (which, in this case, is JWT) and the algorithm used to encode it. The “payload” is the content of the JWT itself — for instance, any claims about the client and its user, as well as what they should have access to. The “signature” at the end is a type of verification. It’s used to confirm that the sender of the JWT (the client) is who they say they are, and that the JWT hasn’t been altered.
The server normally generates the JWT by way of a secret key that encodes the three pieces of information above. Because only the server itself knows this key, the encoding can’t be decrypted like the basic Base64 encoding used for HTTP authentication. The final JWT would look something like this:
Once the JWT is sent back to the client, the server’s work is done. The client stores the JWT locally, usually via something called “local storage” in the browser. The client then sends the JWT alongside future HTTP requests to the API, typically in the “Authorization” header of the requests — specifically, a header called “Bearer.” The content of the header would look something like this:
Authorization: Bearer <token>
The server reads the JWT and decodes it using its secret key. Once decoded, it can be used to authenticate and authorize the client for the requested action. The JWT may additionally contain information about its own expiration time. This creates even less work for the server, as it doesn’t need to keep track of when each client’s access expires (as it would for session-based authentication).
Overall, JWT authentication makes for less burden on the server, and therein lies the main difference between JWT and session-based authentication. With JWT authentication, the server doesn’t store any information in-memory; the JWT token is “self-sufficient.” Thus, there’s little to no “heavy lifting” required on the server-side, leading to a more scalable solution.
For these reasons (speed, security, and less strain on the server-side), JWT token-based authentication tends to be the more favored form of authentication amongst web apps.
Open Authorization (OAuth)
Let’s look at one more option that’s become increasingly popular in recent years when it comes to authentication. Note, though, that this option doesn’t provide an alternative to the methods explored thus far; rather, it offers a framework to do so in a slightly different manner.
Open Authorization, or “OAuth,” is an authentication and authorization framework that allows third party applications to authenticate clients without the need for clients to share credentials directly with the server. Instead, clients are authenticated and authorized via a secure, third party service.
The best example of this is when you go to sign into a website and are offered a number of options for how to do so. For example, you may be given the option to sign in with Google, Facebook, or Twitter. These three sites can act as third party services through which you can be authenticated, giving you access to the original website.
While it’s true that OAuth provides an alternative authentication framework via one of the third party services mentioned above, when it comes down to it, it’s still using one of the same authentication and authorization methods explored above. For example, OAuth usually employs a JWT to authenticate users. If you picked Facebook as the third party service to log in to Medium, Facebook would share your Facebook JWT with Medium, which would contain your authentication and authorization information and allow you to log into the site.
It’s important to note here that you shouldn’t ever fully rely on third party authentication (i.e, you should always offer an alternative, such as email, as well). For one, you may have users that don’t have an account on any of the offered third party services. Still other users like to keep their accounts separate. After all, in an era where more and more social media services are sharing or selling data, keeping your usage of other sites and apps safe from Facebook’s grasp can help keep your online activity more private.
In my next post, I would be discussing the different authorization methods.