Logo
Published on

How to Build Your Own Blog(2): Authentication & Authorization

154 Views

Why?

Since this is a dynamic blog with APIs for creating, updating, and reading blog posts, it's crucial to ensure that unauthorized users cannot create or modify blogs. To protect these APIs, both Authentication and Authorization mechanisms are required.

What?

  • Authentication is the process of verifying the identity of a user or entity. It answers the question, "Who is it?"

  • Authorization is the process of granting or denying access to specific resources or actions based on the user's identity or role. It answers the question, "What can it do?"

Without authentication, authorization becomes insecure and unreliable because there is no way to verify the identity of the user making the request. If you cannot confidently determine "who" is accessing the system, then applying rules about "what" they are allowed to do becomes meaningless. Unauthorized users could gain access to sensitive actions or data simply by bypassing the authentication process, making the system vulnerable to abuse and attacks.

Thus, authentication is a prerequisite for effective authorization to ensure secure and controlled access to resources.

How?

The general idea is to create one user for myself with the permission to create and update blogs. And by default, all unauthenticated users have the permission to get and list blogs.

Defining the User Data Model

First, I need to define the data model for user:

type User struct {
    Username       string `json:"username,omitempty"`
    HashedPassword []byte `json:"hashed_password,omitempty"`
    Salt           []byte `json:"salt,omitempty"`
    CreatedAt      time.Time `json:"created_at,omitempty"`
    UpdatedAt      time.Time `json:"updated_at,omitempty"`
}

Key considerations:

  • Hashed passwords: Storing password in plain text is something we should never do.
  • Salt: A random salt ensures that identical passwords do not generate the same hash and helps defend against rainbow table attacks.
  • Pepper (Optional): One can store hashed password with random salt and a shared secret pepper. This pepper is a static secret that is not stored in the database, adding another layer of protection.

APIs for Signup and Login

Next, I need to define the APIs for signup and login. The signup API is disabled once the first user is created. The login API is used to verify the identity.

Flow for signup and login:

  • Signup:
    • Generate a random salt.
    • Hash the password using the salt (and optionally, a pepper).
    • Store the hashed password, salt, and username in the database.
  • Login:
    • Retrieve the stored salt and hashed password for the user.
    • Hash the entered password using the retrieved salt (and pepper if used).
    • Compare the newly generated hash with the stored hash to verify the identity.

Session Management

In web applications, maintaining state information about a user's interaction is crucial, and this is done through sessions. Without sessions, even after logging in, we cannot authenticate ourselves when making API requests such as creating or updating blogs.

Depending on where the state is stored, sessions are classified into 2 types:

  • Server-side sessions: The session data is stored on the server, and a unique session ID is sent to the client, which is used to identify the session.
  • Client-side sessions: Session data is stored on the client side (usually cookies) with cryptographic techniques.

In this website, I use JWT to manage sessions as a client-side session, because there is no need for maintainability in JWT as no state is stored on server side.

The login flow needs to be updated to generate a JWT that contains user identity information and any relevant claims (e.g., permissions, expiration time). And the JWT is stored in cookies (http-only) securely and included in the Authorization header (e.g., Authorization: Bearer <JWT>) of future API requests.

Login flow

Authorization

I have kept authorization simple since this is a single-user website. The focus is on protecting the APIs responsible for creating and updating blogs, with no need for complex role-based access control or multi-user permissions.

If the request is from an authenticated user, they are automatically authorized to create and update blogs. No additional authorization logic is required since the site is single-user, and authenticated access grants full permissions for blog management.