Building JWT Authentication in Go: A guide with middleware and helper packages
Published: 2023-07-19 19:27:12

In this project, we dive deeply into one of the most critical aspects of any web application: authentication. However, instead of taking the more traditional route, we explore the implementation of JWT authentication in Go, a modern and secure approach to keeping our users authenticated.

The JSON Web Token (JWT) provides a robust and scalable method for handling user authentication and the secure transmission of information between parties. We use the "github.com/golang-jwt/jwt/v4" package to handle the creation and validation of our tokens.

A highlight of the project is the use of middleware to handle the authentication of each request. This allowed the authentication logic to be separated from the rest of the code, improving readability and maintenance.

In addition, we used a variety of helper packages to optimize our application. The Gorilla Mux router, "github.com/gorilla/mux", provides flexible and powerful HTTP request routing. The "github.com/joho/godotenv" package is used for managing environment variables, simplifying the configuration across different development environments.

We adopted "github.com/sirupsen/logrus" to handle server logs, providing flexibility for logging debug events, errors, and general information.

This project is an excellent reference for developers looking to understand how to implement JWT authentication in Go, offering a detailed view of how these concepts can be used in practice. Furthermore, it demonstrates the power of middleware in separating responsibilities and creating clean, easy-to-maintain code.

## JWT Auth Server

This is a simple authentication server in Golang using JWT (JSON Web Tokens) for user authentication. The project is made up of different routes and handlers for signing in, welcoming, refreshing token, and logging out.

## Methods

**main()**

This is the entry point for the server. It sets up the log format, loads environment variables from the .env file, initializes a router, sets up routes, and starts the server.

**Welcome(w http.ResponseWriter, r *http.Request)**

This handler is responsible for welcoming the user. It fetches a token from the cookie, verifies the token's validity, extracts the claims, and returns a welcome message to the user.

**Signin(w http.ResponseWriter, r *http.Request)**

This handler is responsible for logging the user in. It reads credentials from the request body, validates these credentials, creates a JWT token, and returns it in a cookie.

**Refresh(w http.ResponseWriter, r *http.Request)**

This handler is responsible for refreshing the user's JWT token. It fetches the token from the cookie, verifies its validity, creates a new token, and returns it in a cookie.

**Logout(w http.ResponseWriter, r *http.Request)**

This handler is responsible for logging the user out. It simply removes the cookie, effectively invalidating the user's JWT token.

**AuthenticationMiddleware(next http.Handler) http.Handler**

This middleware is responsible for verifying the user's authentication. It's used on routes that require authentication.

## Installation Instructions

First, clone the repository with git clone.

Then, at the root of the project, create a **.env** file with the secret key for the JWT like so: JWT_KEY=yoursecretkey.

Run the command go build to compile the code.

Finally, run the command **./yourfilename** to start the server.

## Testing Instructions

Use a tool like Postman or cURL to make a POST request to localhost:8080/signin with a JSON body containing username and password. You should receive a cookie with a JWT token.

```
{
	"username": "admin",
	"password": "123456"
}
```

Make a GET request to **localhost:8080/welcome** with the JWT token you received. You should receive a welcome message with the username.

Make a POST request to **localhost:8080/refresh** with the JWT token to receive a new token.

Make a GET request to **localhost:8080/logout** to invalidate the token.

The following packages are used in this application:

- **"net/http"**: This is a native Go package that provides HTTP client and server implementations.

- **"github.com/golang-jwt/jwt/v4"**: This package provides the implementation of JWTs (JSON Web Tokens), which are used for user authentication.

- **"github.com/gorilla/mux"**: This package is a powerful URL router and dispatcher. It's used to route incoming HTTP requests to their corresponding handler functions.

- **"github.com/joho/godotenv"**: This package is used to read environment variables from a .env file, which is a common method for configuration in development environments.

- **"encoding/json"**: This is a native Go package that's used for encoding and decoding JSON.

- **"os"** and **"time"**: These are native Go packages used for operating system functionality and time manipulation respectively.

- **"github.com/sirupsen/logrus"**: This package is a flexible logging library. It's used for logging debug information, errors, and general server events.

All code is available at **[https://github.com/mffonseca/golang-jwt-authentication](https://github.com/mffonseca/golang-jwt-authentication)**