---
title: "Secure KrakenD APIs with API Key Authentication"
description: "Secure your KrakenD API using a shared secret."
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/go/krakend/secure-header"
framework: "KrakenD"
language: "Go"
authStrategy: "shared secret header"
pageType: use-case
---

# Secure KrakenD APIs with API Key Authentication

Secure your KrakenD API using a shared secret.

## How Zuplo Handles It

Put Zuplo in front of your KrakenD backend to authenticate API keys and forward a shared secret header so your origin only accepts traffic from Zuplo.

## KrakenD Backend Code

```go
package main

import (
	"context"
	"fmt"
	"net/http"
	"os"

	gin "github.com/gin-gonic/gin"
	krakendgin "github.com/devopsfaith/krakend-gin"
	krakendetc "github.com/devopsfaith/krakend/config"
	"github.com/luraproject/lura/v2/logging"
)

// SecretHeaderMiddleware is a KrakenD middleware for validating a shared secret
func SecretHeaderMiddleware(secretKey string) gin.HandlerFunc {
	return func(c *gin.Context) {
		secret := c.GetHeader("X-Shared-Secret")
		expectedSecret := os.Getenv("SHARED_SECRET")

		if expectedSecret == "" {
			c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "Server configuration error"})
			return
		}

		if secret == "" {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "No secret provided"})
			return
		}

		// Perform timing-safe comparison
		if !timingSafeCompare(secret, expectedSecret) {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid secret"})
			return
		}

		c.Next()
	}
}

func timingSafeCompare(a, b string) bool {
	if len(a) != len(b) {
		return false
	}
	result := 0
	for i := 0; i < len(a); i++ {
		result |= int(a[i] ^ b[i])
	}
	return result == 0
}

func main() {
	cfg := krakendetc.Parser.Parse("/path/to/krakend/config.json")
	logger, _ := logging.NewLogger("DEBUG", os.Stdout, "[KRAKEND]")

	routerFactory := krakendgin.DefaultFactoryProxyFactory(logger, krakendgin.DefaultRouterFactory)
	engine := krakendgin.NewEngine(logger, cfg, routerFactory)

	// Add the middleware to the router
	engine.Use(SecretHeaderMiddleware("X-Shared-Secret"))

	engine.GET("/protected", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "Access granted",
		})
	})

	fmt.Println("Listening on :8080")
	engine.Run(":8080")
}
```

## Example Request

```bash
curl -X GET \
  'https://your-api.zuplo.dev/your-route' \
  -H 'Authorization: Bearer YOUR_API_KEY'
```

## Learn More

- [API Key Authentication on Zuplo](https://zuplo.com/docs/policies/api-key-auth-inbound)
- [JWT Authentication on Zuplo](https://zuplo.com/docs/policies/open-id-jwt-auth-inbound)
- [All use cases](https://zuplo.com/use-cases)
