Authentication and Authorization

2022-03-09

These two terms sound similar but they mean different things. Authentication is about verifying who the user is. Authorization is about verifying what the user is allowed to do. Both are important when building applications that have user accounts and different levels of access.

Authentication

The most common way to authenticate a user is through a login form where they enter their username or email and a password. The application checks if the credentials match what is stored in the database. If they match, the user is authenticated.

Passwords should never be stored as plain text in the database. They should be hashed using a hashing algorithm like bcrypt. When a user logs in, the application hashes the submitted password and compares it with the stored hash. This way, even if someone gets access to the database, they cannot see the actual passwords.

After a user logs in, we need a way to remember that they are authenticated for subsequent requests. There are two common approaches: sessions and tokens.

Sessions store the user's login state on the server. When a user logs in, the server creates a session and sends a session ID to the client as a cookie. On every request, the client sends the cookie back and the server checks if the session is still valid.

Tokens work differently. When a user logs in, the server generates a token, usually a JWT (JSON Web Token), and sends it to the client. The client stores the token and includes it in the header of every request. The server can verify the token without needing to store any session data. This makes tokens more suitable for applications that need to scale across multiple servers.

Authorization

Once we know who the user is, we need to control what they can access. A common approach is role-based access control. We assign roles to users, for example admin, editor, and viewer. Each role has a set of permissions. An admin can create, read, update, and delete. An editor can create, read, and update. A viewer can only read.

In the application, before processing a request, we check if the user's role has the required permission for that action. For example, if someone tries to delete a record but they only have the viewer role, the request is rejected with a 403 Forbidden status.

Practical Example

In a React application, after a user logs in and receives a token, we usually store it in memory or local storage. Then we create an API helper or interceptor that automatically attaches the token to every outgoing request. On the frontend, we can also conditionally render UI elements based on the user's role. For example, only showing the delete button to admin users.

On the backend, we create middleware that extracts the token from the request header, verifies it, and attaches the user information to the request object. Then in each route handler, we can check the user's role before processing the request.