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

15 Creating Session-based Authentication Middleware Using `httprouter` in Golang

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

In this article, we will walk through the steps of building Session-based Authentication Middleware using Golang and the httprouter library. This middleware will help verify user sessions for incoming HTTP requests.

What is Session-based Authentication?

Session-based authentication is an authentication method where a user logs in through an application, and the server stores session information in the form of a session ID, either on the server or as a cookie in the user’s browser. Each time the user accesses a protected resource, the server verifies the session.

For this example, we will use httprouter, a fast and minimalistic HTTP router for Golang, to create the session-based authentication middleware.

Step 1: Setting Up the Golang Project

If you haven’t already, set up your Golang project with the following steps:

  1. Create a project directory via the terminal or your preferred IDE.
  2. Initialize the Go project.
    bash
    1go mod init session-auth-example

Step 2: Installing Dependencies

First, we need to add dependencies for httprouter and gorilla/sessions, which we will use to manage user sessions.

Install them using the following commands:

bash
1 go get github.com/julienschmidt/httprouter
2 go get github.com/gorilla/sessions

Step 3: Creating the Authentication Middleware

Now, we will create middleware to validate sessions for every incoming HTTP request. We need:

  1. A store from gorilla/sessions to manage session storage.
  2. A middleware function to check whether a valid session exists.

authMiddleware.go

go
 1package main
 2
 3import (
 4    "github.com/gorilla/sessions"
 5    "github.com/julienschmidt/httprouter"
 6    "net/http"
 7    "log"
 8)
 9
10var store = sessions.NewCookieStore([]byte("secret-key"))
11
12// AuthMiddleware checks if the user session is valid
13func AuthMiddleware(next httprouter.Handle) httprouter.Handle {
14    return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
15        // Retrieve session from request
16        session, err := store.Get(r, "session-name")
17        if err != nil {
18            http.Error(w, "Could not get session", http.StatusInternalServerError)
19            return
20        }
21
22        // Check if the "user" session exists
23        user, ok := session.Values["user"]
24        if !ok || user == nil {
25            http.Error(w, "Unauthorized", http.StatusUnauthorized)
26            return
27        }
28
29        // Proceed if authentication is valid
30        next(w, r, ps)
31    }
32}
33
34func main() {
35    router := httprouter.New()
36    router.GET("/private", AuthMiddleware(privatePage))
37
38    log.Fatal(http.ListenAndServe(":8080", router))
39}
40
41// Handler for a protected private page
42func privatePage(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
43    w.Write([]byte("Welcome to the private page"))
44}

Step 4: Creating a Login Endpoint to Set a Session

To test authentication, we need an endpoint to log in. This endpoint initializes a session when a user successfully logs in.

loginHandler.go

go
 1package main
 2
 3import (
 4    "github.com/julienschmidt/httprouter"
 5    "net/http"
 6    "log"
 7)
 8
 9func loginHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
10    session, _ := store.Get(r, "session-name")
11
12    // Set user session (e.g., after successful login)
13    session.Values["user"] = "authenticated-user"
14    session.Save(r, w)
15
16    w.Write([]byte("Login successful"))
17}
18
19func main() {
20    router := httprouter.New()
21    router.GET("/login", loginHandler)
22    router.GET("/private", AuthMiddleware(privatePage))
23
24    log.Fatal(http.ListenAndServe(":8080", router))
25}

Step 5: Writing Unit Tests for the Middleware

Writing unit tests ensures that our middleware functions as expected. We will use Golang’s standard testing package.

authMiddleware_test.go

go
 1package main
 2
 3import (
 4    "github.com/julienschmidt/httprouter"
 5    "net/http"
 6    "net/http/httptest"
 7    "testing"
 8)
 9
10func TestAuthMiddleware(t *testing.T) {
11    router := httprouter.New()
12    router.GET("/private", AuthMiddleware(privatePage))
13
14    req, err := http.NewRequest("GET", "/private", nil)
15    if err != nil {
16        t.Fatal(err)
17    }
18
19    rr := httptest.NewRecorder()
20    router.ServeHTTP(rr, req)
21
22    if status := rr.Code; status != http.StatusUnauthorized {
23        t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusUnauthorized)
24    }
25}
26
27func TestLogin(t *testing.T) {
28    router := httprouter.New()
29    router.GET("/login", loginHandler)
30
31    req, err := http.NewRequest("GET", "/login", nil)
32    if err != nil {
33        t.Fatal(err)
34    }
35
36    rr := httptest.NewRecorder()
37    router.ServeHTTP(rr, req)
38
39    if rr.Code != http.StatusOK {
40        t.Errorf("Expected status OK, got %v", rr.Code)
41    }
42}

Explanation of Unit Tests:

  1. TestAuthMiddleware: Ensures that the middleware returns a 401 Unauthorized status if a user session is invalid.
  2. TestLogin: Confirms that the login request succeeds with a 200 OK status.

Step 6: Conclusion

Using Golang, we can efficiently create Session-based Authentication middleware with httprouter. In this example, we built a middleware that verifies user sessions stored in cookies to secure protected endpoints.

For more information on Golang and HTTP routing, check out:

This guide outlines the fundamentals of implementing session-based authentication using middleware in Golang. Feel free to explore further enhancements and refinements!

Related Articles

💬 Comments