---
title: "Add JWT Authentication to Your Buffalo API"
description: "Secure your Buffalo API using JWT authentication with JWKS."
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/go/buffalo/jwt-backend"
framework: "Buffalo"
language: "Go"
authStrategy: "JWT with JWKS"
pageType: use-case
---

# Add JWT Authentication to Your Buffalo API

Secure your Buffalo API using JWT authentication with JWKS.

## How Zuplo Handles It

Let Zuplo issue short-lived JWTs signed with a JWKS your Buffalo backend can verify — no long-lived API keys touch your origin.

## Buffalo Backend Code

```go
package main

import (
    "fmt"
    "net/http"
    "strings"

    "github.com/gobuffalo/buffalo"
    "github.com/MicahParks/keyfunc"
    "github.com/dgrijalva/jwt-go"
)

// Define the issuer
const issuer = "https://my-api-a32f34.zuplo.api/__zuplo/issuer"

func main() {
    // Create a new Buffalo app
    app := buffalo.New(buffalo.Options{})

    // Middlewares
    app.Use(JWTMiddleware)

    // Protected route
    app.GET("/protected", ProtectedHandler)

    // Start the Buffalo app
    app.Listen(":3000")
}

// JWTMiddleware is a middleware to validate JWT
func JWTMiddleware(next buffalo.Handler) buffalo.Handler {
    return func(c buffalo.Context) error {
        tokenString := getTokenFromHeader(c.Request())

        if tokenString == "" {
            return c.Render(http.StatusUnauthorized, r.JSON(map[string]string{"error": "No token provided"}))
        }

        // Load the JWKS
        jwksURL := fmt.Sprintf("%s/.well-known/jwks.json", issuer)
        jwks, err := keyfunc.Get(jwksURL, keyfunc.Options{})
        if err != nil {
            return c.Render(http.StatusInternalServerError, r.JSON(map[string]string{"error": "Failed to load JWKS"}))
        }

        // Validate the token
        token, err := jwt.Parse(tokenString, jwks.Keyfunc)
        if err != nil {
            return c.Render(http.StatusUnauthorized, r.JSON(map[string]string{"error": "Invalid token", "details": err.Error()}))
        }

        claims := token.Claims.(jwt.MapClaims)
        c.Set("user", claims)

        return next(c)
    }
}

// ProtectedHandler is an example of a protected route
func ProtectedHandler(c buffalo.Context) error {
    user := c.Value("user")
    return c.Render(http.StatusOK, r.JSON(map[string]interface{}{
        "message": "Access granted",
        "user":    user,
    }))
}

// getTokenFromHeader extracts the token from the Authorization header
func getTokenFromHeader(r *http.Request) string {
    authHeader := r.Header.Get("Authorization")
    if authHeader == "" {
        return ""
    }
    parts := strings.Split(authHeader, " ")
    if len(parts) != 2 || strings.ToLower(parts[0]) != "bearer" {
        return ""
    }
    return parts[1]
}
```

## 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)
