Authentication Deep Dive Part 1

Authentication in a nutshell

Adebayo Taiwo
8 min readApr 20, 2023

The world wide web as we know it is a public repository of resources (web pages, documents, images, music etc.) on the internet, this implies that anyone with a device connected to the internet can access any resource online.

People use various devices and applications to access the internet these devices or applications only send information about themselves to the server implying that the server only know information about these devices or applications not the person using them.

While this may be desirable for some websites such as open forum, blogs and feed (assuming they are not tracking users’ activities for recommendation and ads) that put information on the internet for public consumption. Most applications need means of identifing who exactly is making the request to access their resources and if they can access this particular resrouces or not.

The process of verifying the identity of the person or device making a request to access a resource is what we called Authentication. Being able to identify who is making a request is only half of the problem, applications need to know whether or not this particular user or device can actually access this resource and perform the requested action this is what is called Authorization which we will cover in depth in later article(s).

For now it is okay to know that both authentication and authorization goes hand in hand and that authorization is the next step after authenticating a user or device.

The HTTP protocol which is used for communicating between entities(serves and clients) on the internet is stateless, what do I mean by stateless? Well, this mean that the protocol doesn’t keep track of requests made (there is no link between requests), once a request is made and response returned, the protocol forget everything about the request (what is done during the request or what it is all about) and subsequent requests (by the same device or user) is treated as new.

If a user is able to verify it’s identity durnig a request, on subsequent requests our application(s) will not know about this again and they will need to keep authenticating, this is a nuisance to users imagine having to provide your username and password everytime you want to send message on facebook(horrible right?)

From the early days of the internet people have come up with different methods to solve this problem and make their application stateful. There are two primary ways in which developers solved this, which is with session and cookies and authentication token.

Session and Cookies

We can’t really talk about authentication without first understanding what session and cookies are, as they are the building block and what make user identification possible, the http protocol as we said is stateless, to solve this problem developers come up with sessions and cookies

Cookies are text-files with small pieces of data stored on the client (device making the request such as browsers) that are use to keep track or identify a user while a Session(HTTP) is information stored on a server momentarily (may span days or months depending on implementation) so that the server can keep track of a user or device activities and also link requests together.

When a device first make a request to access a resource, the server in order to be able to identify this device on subsequent requests will store information about this request in memory or in cache (that is a session) and send the key to access this information to the client (delicous cookies). the client then keep sending this key with each subsequent request to the server with this the server will be able to track the requests and identify who or what is making it.

How is it done?

As explained in the session and cookies session, when a device make request to the server, the server store a piece of information about the request and send the key to retrieve this information to the client. The server have to instruct the client to save this key and keep sending it on subsequent requests, this is added as part of the metadata of the response and is not part of the body of the response(the actual resource or other information the client want).

This metadata is what we call Header (there is a lot to say on headers but we will only limit ourselves to cookies). As said the Header is just a metadata that provide more information about the request (whether the resources is avaible or not) and other instruction to the client, one of this instructions is the Set-Cookie instruction or header. this instruct the client to store the provided information(our cookie) and send it back to the server on subsequent requests. the syntax for this is Set-Cookie : <cookie-name>: <cookie-value>.

Below is a simple python code (flask), clients are required to submit a form to this endpoint, on submission the server store the submitted name in a dictionary with a unique key, by using the make_response method from flask we instruct the browser to set a cookie named “name_cookie” with it’s value being the unique id to access the stored name.

@app.route("/set_cookie", methods=["POST"])
def get_cookies():
name = request.form.get("name")
if not name:
return redirect(url_for("home"))
id = "".join(random.sample(letters, 10))
names[id] = name
resp = make_response(render_template("index.html"))
resp.set_cookie("name_cookie", id)
return resp
Set-Cookie header

The response Headers tab here contain all the metadata about the response, such as the state of the connection, how much stuff is received, the type of content being sent, date, the server which served the request and lastly the Set-Cookie header which is the instruction received from the server telling the browser to save and keep sending this information on subsequent requests.

Browser save the received cookie in it’s memory
On subsequent requests the client(browser is sending our cookie back to the server

with this information set on both end the server will be able to recognize and track the user on subsequent requests (as long as the cookie and session are still on the client and server respectively)

Authentication Token

One of the disadvantages of using cookies is that it is limited to the web browser and there is limit to the amount of information(4kb in general) we can store with cookies. Applications need to authenticate users or devices outside of the browser, such as requests from a mobile app or from another applications such as when you want to execute trade on your binance account from your python app.

Also cookies can be vulnerable to Cookies can be vulnerable to attacks, such as cross-site scripting (XSS) and cross-site request forgery (CSRF), which can be used to steal user information or impersonate the user.

Also both client and server are required to store information on both end in order to be able to keep track of who or what is making requests, users can tamper with this data or even delete it.

With Authentication token, when a client make an authentication request to the server, the server first verify if the authentication details (e.g password and email) are correct, if so the server then encrypt a piece of information to identify the user (such as id, username or email) along with information about the token itself such as what it can be used for, where it can be used and it’s expiry time.

After encryption, the server will send this token to the client to be sent on subsequent requests. With this method there is no instruction on how this should be sent, the developer of the server(the application serving the requests) will have to communicate how this token will be used to the client’s developer, with this method it is no longer the task of the application being used to send the token but the developers themselves.

There are various ways in which this information can be sent depending on implementation, the token can be sent as part of the body of a request, attached to the information being submitted when the request is made or used as query param but the most used method is sending the token along in the header of the request.

There is a dedicated header for this purpose which is the HTTP Authorization Header (just like in the Cookie header). The syntax for setting this header is: Authorization: <type> <credentials>

The type here is used specify the scheme we’re using, since Authentication header is a standardized header there are a handful of them, the one we’ll focus on is the Bearer scheme which is the one mostly used with authentication token.

The client on receiving an authentication token from a server store it somewhere (local or session storage in browsers), whenever the client want to make a request it set the token on it authorization header and send it along with the request.

The server on receiving a request to access a protected endpoint will check for the presence of this token in the header, if it’s not there the server send an unanthenticated response, if the token is set and successfully retrived the server can then try to decode the token, retrieve the content and get the authenticated user, the server also check if the token can be used to access the resource being requested(authorization?).

How is it done?

To demonstrate how this is done we’ll implement the same functionality as we did in the cookies and session section using token authentication.

I add the cryptography library for encrytion and decription
I add the cryptography library for encryption and decryption
@app.route("/get_auth_token", methods=["POST"])
def get_auth_token():
name = request.form.get("name")

if not name:
return redirect(url_for("token_home"))
print(name)
encrypted = f.encrypt(name.encode())
return {"token": encrypted.decode()}

I create a get_auth_token endpoint the same as the set_cookie endpoint but here we are encrypting the submitted name and send it back to the client (note that we’re not saving anything on the server).

@app.route("/retrieve_user")
def retrieve_user():
auth_header = request.headers.get("Authorization")
if auth_header:
auth_token = auth_header.split(" ")[1]
name = f.decrypt(auth_token.encode())
print(name)
return {"user": name.decode()}

Endpoint to retrieve the user, we first check if the client set the authorization header in their requests, if they did we retrieve the token and decrypt it if everything goes well we send back the decrypted name.

Javascript function to get and retrieve name

In the session and cookies section we’re not submitting the form ourselves but it is the browser that submit the form and make sure any cookies set are send authomatically to the server. But here we need to submit the form manually and extract the sent token and also we need to make sure our code is sending the token to any protected endpoint we are trying to access.

Note: This is a very simplified version of token based authentication, in production developers use Json Web Token(JWT) which is more robust and provide a lot of flexibilities and options but the idea is all the same.

The codes used for this article can be found on this github repo https://github.com/mover-elite/authentication

After learning how we can make our application remember users i.e we have add session to our app, Now we’ll learn how about the different methods of authentication and how to implement them.

Types of Authentication

  1. Password Authentication
  2. Passwordless Authentication
  3. Two Factor Authentication
  4. Multi Factor Authentication
  5. Single Sign On and
  6. OAuth 2.0

We’ll see how these are implemented and implement our own in upcoming articles in this series

Don’t miss my next articles! Follow my Medium account to stay up-to-date on my latest content.

--

--

Adebayo Taiwo

Developer and writer, linux and python evangelist. Knowledge seeker, enjoys learning and implementing cool stuffs with code.