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
- Basic understanding of Golang: Familiarity with functions, structures, and package operations.
- Golang installed: Ensure you have Go installed on your computer.
- 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!