programming

14 How to Build API Key Authentication Middleware with Unit Tests Using httprouter in Golang

APIs (Application Programming Interfaces) play a crucial role in connecting various applications or services. To ensure your application remains secure and protected from unauthorized access, implementing authentication methods such as API Key Authentication is essential. In this article, we will go through a step-by-step guide on how to create API Key Authentication middleware using httprouter in Golang, along with unit tests for each function to ensure reliability.

What is API Key Authentication Middleware?

Middleware is a software component that sits between the server and the application to process HTTP requests. In the context of APIs, API Key Authentication middleware verifies every request to ensure it contains a valid API key. This prevents API misuse by restricting access only to registered applications.

The middleware will check whether the API-Key header in the request matches a valid API key. If it is invalid, the request will be rejected with a 401 Unauthorized status.

Steps to Implement API Key Authentication Middleware

Here’s how to build API Key Authentication middleware with httprouter in Golang, including unit tests for each function.

1. Install httprouter Library

If you haven’t installed it yet, add the httprouter library by running:

go get github.com/julienschmidt/httprouter

2. Project Structure

A simple project structure looks like this:

/go-api-key-auth
    /main.go
    /middleware.go
    /middleware_test.go
  • main.go: The entry point of the application.
  • middleware.go: Contains the API key authentication logic.
  • middleware_test.go: Contains unit tests.

3. Implementing the Middleware

First, create the API Key Authentication middleware to validate API keys.

middleware.go

package main

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

// validAPIKey is the pre-defined valid API key
const validAPIKey = "1234567890"

// APIKeyMiddleware is a middleware function to verify API Key in requests
func APIKeyMiddleware(next httprouter.Handle) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		apiKey := r.Header.Get("API-Key")

		// Reject request if API key is missing or invalid
		if apiKey != validAPIKey {
			http.Error(w, "Unauthorized", http.StatusUnauthorized)
			return
		}

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

// protectedEndpoint is an API endpoint secured by API key authentication
func protectedEndpoint(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	w.Write([]byte("Access granted to protected endpoint!"))
}

4. Implementing the Main Function

Now, create the main function to run the server and define routes for the protected endpoint.

main.go

package main

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

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

	// Apply middleware to the protected endpoint
	router.GET("/protected", APIKeyMiddleware(protectedEndpoint))

	// Start the server
	log.Fatal(http.ListenAndServe(":8080", router))
}

5. Writing Unit Tests

After implementing the middleware, we need to add unit tests to verify its functionality. These tests ensure that API key validation works correctly and the endpoint responds as expected.

middleware_test.go

package main

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

// Unit test for APIKeyMiddleware
func TestAPIKeyMiddleware(t *testing.T) {
	// Create router instance
	router := httprouter.New()

	// Attach protected handler with middleware
	router.GET("/protected", APIKeyMiddleware(protectedEndpoint))

	tests := []struct {
		apiKey       string
		expectedCode int
	}{
		{"1234567890", http.StatusOK},           // Valid API key
		{"invalid-api-key", http.StatusUnauthorized}, // Invalid API key
		{"", http.StatusUnauthorized},           // Missing API key
	}

	for _, tt := range tests {
		t.Run(tt.apiKey, func(t *testing.T) {
			req, err := http.NewRequest("GET", "/protected", nil)
			if err != nil {
				t.Fatal(err)
			}

			// Add API Key to request header
			req.Header.Set("API-Key", tt.apiKey)

			// Create recorder to capture response
			rr := httptest.NewRecorder()

			// Serve request
			router.ServeHTTP(rr, req)

			// Check response status code
			if rr.Code != tt.expectedCode {
				t.Errorf("Expected status %v, got %v", tt.expectedCode, rr.Code)
			}
		})
	}
}

Running the Unit Tests

To run the unit tests, execute the following command:

go test -v

If all tests pass, you will see an output like this:

=== RUN   TestAPIKeyMiddleware
--- PASS: TestAPIKeyMiddleware (0.00s)
PASS
ok   <your-package-name>  0.004s

6. Running the Server

To start the server, run:

go run main.go

Then, access the protected API using curl or any HTTP client.

Conclusion

By following this tutorial, you have successfully built API Key Authentication middleware using httprouter in Golang. You also implemented unit tests to ensure your middleware and application logic work correctly. Using middleware like this is essential for keeping your API secure and preventing unauthorized access.

For further learning on Golang, check out these related articles:

With this knowledge, you’re now ready to develop more secure and robust APIs!

comments powered by Disqus