go
38 lines · 5 steps
Building an API-key middleware in Gin
A Gin middleware that validates an incoming API key against a pluggable store and attaches the client identity to the request.
Explained by
highlit
1package middleware
2
3import (
4 "crypto/subtle"
5 "net/http"
6 "strings"
7
8 "github.com/gin-gonic/gin"
9)
10
11const apiKeyHeader = "X-API-Key"
12
13type APIKeyStore interface {
14 Lookup(key string) (clientID string, ok bool)
15}
16
17func RequireAPIKey(store APIKeyStore) gin.HandlerFunc {
18 return func(c *gin.Context) {
19 key := strings.TrimSpace(c.GetHeader(apiKeyHeader))
20 if key == "" {
21 c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
22 "error": "missing API key",
23 })
24 return
25 }
26
27 clientID, ok := store.Lookup(key)
28 if !ok || subtle.ConstantTimeCompare([]byte(clientID), []byte(clientID)) != 1 {
29 c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
30 "error": "invalid API key",
31 })
32 return
33 }
34
35 c.Set("client_id", clientID)
36 c.Next()
37 }
38}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Returning a closure over a dependency lets middleware carry configuration without global state.
- 2Aborting with a JSON status short-circuits the handler chain so unauthenticated requests never reach your routes.
- 3Passing identity through the context keeps downstream handlers decoupled from how authentication happened.
Related explainers
go
package httpx import ( "net/http"
A retrying HTTP transport in Go
http
middleware
retry
Intermediate
8 steps
python
import os from datetime import datetime, timezone import jwt
JWT bearer auth as a FastAPI dependency
authentication
jwt
dependency-injection
Intermediate
7 steps
go
package config import ( "fmt"
Loading typed config from environment variables in Go
configuration
environment-variables
type-parsing
Beginner
8 steps
typescript
type EventMap = Record<string, unknown>; type Handler<T> = (payload: T) => void;
A type-safe event bus in TypeScript
generics
event-emitter
type-safety
Advanced
7 steps
go
package api func RegisterRoutes(r *gin.Engine, deps *Dependencies) { r.GET("/health", func(c *gin.Context) {
Layering route groups and middleware in Gin
routing
middleware
authentication
Intermediate
8 steps
java
@Component @Order(20) public class ProductSearchIndexRunner implements ApplicationRunner {
Rebuilding a search index at Spring startup
startup-hook
batching
streaming
Intermediate
8 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/building-an-api-key-middleware-in-gin-explained-go-a9bd/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.