programming

11 Membuat Middleware Basic Authentication HTTP Router pada Golang

Basic Authentication is a simple authentication method where the client sends credentials (username and password) in the header of each HTTP request. In this article, we will learn how to create Basic Authentication middleware in Golang using the httprouter library.

This article is intended for beginner programmers, providing detailed steps and explanations to facilitate understanding.


Prerequisites

  1. Basic understanding of Golang: Familiarity with functions, structures, and package operations.
  2. Golang installed: Ensure you have Go installed on your computer.
  3. Required library: Install the github.com/julienschmidt/httprouter library with the following command:
go get github.com/julienschmidt/httprouter

Step 1: Project Structure

Create the following project structure:

project-root/
├── main.go
├── middleware/
│   └── basic_auth.go
├── handlers/
│   └── user.go

The main.go file serves as the application’s entry point, while middleware/ and handlers/ are used to separate middleware and endpoint functions.


Step 2: Creating the Main File

Open main.go and add the following code:

package main

import (
	"fmt"
	"log"
	"net/http"
	"github.com/julienschmidt/httprouter"
	"project-root/middleware"
	"project-root/handlers"
)

func main() {
	router := httprouter.New()

	// Public endpoint without authentication
	router.GET("/public", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		fmt.Fprint(w, "Public endpoint does not require authentication!\n")
	})

	// Private endpoint using Basic Authentication middleware
	router.GET("/private", middleware.BasicAuth(handlers.PrivateHandler))

	log.Println("Server running at http://localhost:8080")
	log.Fatal(http.ListenAndServe(":8080", router))
}

The above code defines a public endpoint and a private endpoint protected by Basic Authentication middleware.


Step 3: Creating Basic Authentication Middleware

Open middleware/basic_auth.go and write the following code:

package middleware

import (
	"encoding/base64"
	"net/http"
	"strings"
	"github.com/julienschmidt/httprouter"
)

var validUsers = map[string]string{
	"admin": "password123",
	"user":  "password456",
}

func BasicAuth(next httprouter.Handle) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		authHeader := r.Header.Get("Authorization")
		if authHeader == "" || !strings.HasPrefix(authHeader, "Basic ") {
			http.Error(w, "Unauthorized", http.StatusUnauthorized)
			return
		}

		// Decode Base64 credentials
		payload, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(authHeader, "Basic "))
		if err != nil {
			http.Error(w, "Invalid authentication token", http.StatusUnauthorized)
			return
		}

		cred := strings.SplitN(string(payload), ":", 2)
		if len(cred) != 2 || !validateUser(cred[0], cred[1]) {
			http.Error(w, "Invalid username or password", http.StatusUnauthorized)
			return
		}

		// Proceed to the next handler if valid
		next(w, r, ps)
	}
}

func validateUser(username, password string) bool {
	if pass, ok := validUsers[username]; ok {
		return pass == password
	}
	return false
}

This middleware reads the Authorization header, decodes Base64-encoded credentials, and validates the username and password using the in-memory validUsers map.


Step 4: Creating the Private Endpoint Handler

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

package handlers

import (
	"fmt"
	"net/http"
	"github.com/julienschmidt/httprouter"
)

func PrivateHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	fmt.Fprint(w, "Welcome to the private endpoint! You have successfully authenticated.\n")
}

This handler will only be accessible if the provided Basic Authentication credentials are valid.


Step 5: Testing the Application

Run the application using the following command:

go run main.go

Try accessing the following endpoints using tools like curl or Postman.

1. Public Endpoint (No Authentication Required)

curl http://localhost:8080/public

Response:

Public endpoint does not require authentication!

2. Private Endpoint (With Authentication)

To access the private endpoint, add an Authorization header with the Basic value followed by Base64-encoded username and password.

For example, for the username admin and password password123:

curl -H "Authorization: Basic YWRtaW46cGFzc3dvcmQxMjM=" http://localhost:8080/private

If valid, the response will be:

Welcome to the private endpoint! You have successfully authenticated.

If the credentials are incorrect, you will receive a 401 Unauthorized error response.


Conclusion

By following these steps, you have successfully created Basic Authentication middleware in Golang using httprouter. This middleware provides a simple way to protect API endpoints, though it is not secure for production environments unless used with HTTPS.

For better security, consider using more modern authentication methods such as OAuth or JWT in your production applications. Happy coding!

comments powered by Disqus