Skip to content
Santekno.com | Level Up Your Engineering Skills
EN
📖 0%
21 Jan 2025 · 4 min read ·Article 69 / 119
Go

10 Creating Authentication Middleware Using JWT with Httprouter in Golang

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

In modern application development, authentication is one of the most crucial components. JSON Web Tokens (JWT) is a popular method for handling token-based authentication. In this article, we will create an authentication middleware using JWT in Golang with the httprouter library from julienschmidt .

This article is designed for beginner programmers with detailed steps and explanations to make it easy to follow.


Prerequisites

  1. Basic understanding of Golang: You should have a basic understanding of Golang, including functions, structures, and modules.
  2. Golang installed: Ensure you have Go installed on your system.
  3. Required libraries: We will use the following additional libraries:
    • github.com/golang-jwt/jwt/v4 for managing JWT.
    • github.com/julienschmidt/httprouter for routing.

To install these libraries, use the following command:

bash
1go get github.com/golang-jwt/jwt/v4 github.com/julienschmidt/httprouter

Step 1: Creating the Project Structure

Create the following folder structure:

bash
1project-root/
2├── main.go
3├── middleware/
4│   └── auth.go
5├── handlers/
6│   └── user.go
7├── utils/
8│   └── jwt.go

The main.go file serves as the entry point of the application, while the other folders organize various functions and middleware.


Step 2: Creating the Main File

Open main.go and add the following code:

go
 1package main
 2
 3import (
 4	"fmt"
 5	"log"
 6	"net/http"
 7	"github.com/julienschmidt/httprouter"
 8	"project-root/middleware"
 9	"project-root/handlers"
10)
11
12func main() {
13	router := httprouter.New()
14
15	// Public endpoint without authentication
16	router.GET("/public", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
17		fmt.Fprint(w, "Public endpoint does not require authentication!\n")
18	})
19
20	// Private endpoint using authentication middleware
21	router.GET("/private", middleware.JWTAuth(handlers.PrivateHandler))
22
23	log.Println("Server running at http://localhost:8080")
24	log.Fatal(http.ListenAndServe(":8080", router))
25}

The above code provides a minimal application setup using middleware for private endpoints.


Step 3: Creating JWT Middleware

Open middleware/auth.go and add the following code:

go
 1package middleware
 2
 3import (
 4	"net/http"
 5	"strings"
 6	"github.com/golang-jwt/jwt/v4"
 7	"project-root/utils"
 8	"github.com/julienschmidt/httprouter"
 9)
10
11func JWTAuth(next httprouter.Handle) httprouter.Handle {
12	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
13		tokenString := extractToken(r)
14		if tokenString == "" {
15			http.Error(w, "Authorization header missing", http.StatusUnauthorized)
16			return
17		}
18
19		// Validate token
20		claims, err := utils.ValidateJWT(tokenString)
21		if err != nil {
22			http.Error(w, "Invalid token", http.StatusUnauthorized)
23			return
24		}
25
26		// Proceed to the next handler
27		next(w, r, ps)
28	}
29}
30
31func extractToken(r *http.Request) string {
32	bearer := r.Header.Get("Authorization")
33	if bearer == "" || !strings.HasPrefix(bearer, "Bearer ") {
34		return ""
35	}
36	return strings.TrimPrefix(bearer, "Bearer ")
37}

This middleware extracts the token from the Authorization header, validates it, and proceeds to the next handler if the token is valid.


Step 4: Creating the Private Endpoint Handler

Open handlers/user.go and add the following code:

go
 1package handlers
 2
 3import (
 4	"fmt"
 5	"net/http"
 6	"github.com/julienschmidt/httprouter"
 7)
 8
 9func PrivateHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
10	fmt.Fprint(w, "Welcome to the private endpoint! Your token is valid.\n")
11}

This handler can only be accessed if the JWT middleware successfully validates the token.


Step 5: Creating Utility Functions for JWT

Open utils/jwt.go and add the following code:

go
 1package utils
 2
 3import (
 4	"errors"
 5	"time"
 6	"github.com/golang-jwt/jwt/v4"
 7)
 8
 9var secretKey = []byte("super_secret")
10
11type CustomClaims struct {
12	Username string `json:"username"`
13	jwt.RegisteredClaims
14}
15
16func GenerateJWT(username string) (string, error) {
17	claims := CustomClaims{
18		Username: username,
19		RegisteredClaims: jwt.RegisteredClaims{
20			ExpiresAt: jwt.NewNumericDate(time.Now().Add(1 * time.Hour)),
21		},
22	}
23	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
24	return token.SignedString(secretKey)
25}
26
27func ValidateJWT(tokenString string) (*CustomClaims, error) {
28	token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
29		return secretKey, nil
30	})
31	if err != nil {
32		return nil, err
33	}
34
35	claims, ok := token.Claims.(*CustomClaims)
36	if !ok || !token.Valid {
37		return nil, errors.New("invalid token")
38	}
39
40	return claims, nil
41}

This file contains functions for creating and validating JWT tokens. GenerateJWT is used to create a token, while ValidateJWT checks its validity.


Step 6: Testing the Application

Run the application with the following command:

bash
1go run main.go

Test the endpoints using curl or Postman.

1. Public Endpoint (No Token Required)

bash
1curl http://localhost:8080/public

Response:

bash
1Public endpoint does not require authentication!

2. Private Endpoint (With Token)

First, generate a token using GenerateJWT (implement it in another app or manually for testing). Then, use the token to access the private endpoint:

bash
1curl -H "Authorization: Bearer <YOUR_TOKEN>" http://localhost:8080/private

If the token is valid, the response will be:

bash
1Welcome to the private endpoint! Your token is valid.

Conclusion

You have successfully created an authentication middleware using JWT in Golang with httprouter. With this approach, you can ensure that sensitive endpoints are only accessible to authenticated users. This middleware is also flexible for production applications.

Hopefully, this article helps you understand the basics of JWT in Golang. If you have any questions, feel free to ask or explore further!

Related Articles

💬 Comments