jwtware

package module
v1.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 13, 2026 License: MIT Imports: 10 Imported by: 3

README


id: jwt

JWT

Release Discord Test

JWT returns a JSON Web Token (JWT) auth middleware. For valid token, it sets the token in Ctx.Locals (and in the underlying context.Context when PassLocalsToContext is enabled) and calls next handler. For invalid token, it returns "401 - Unauthorized" error. For missing token, it returns "400 - Bad Request" error.

Special thanks and credits to Echo

Compatible with Fiber v3.

Go version support

We only support the latest two versions of Go. Visit https://go.dev/doc/devel/release for more information.

Install

go get -u github.com/gofiber/fiber/v3
go get -u github.com/gofiber/contrib/v3/jwt
go get -u github.com/golang-jwt/jwt/v5

Signature

jwtware.New(config ...jwtware.Config) func(fiber.Ctx) error
jwtware.FromContext(ctx any) *jwt.Token    // jwt "github.com/golang-jwt/jwt/v5"

FromContext accepts a fiber.Ctx, fiber.CustomCtx, *fasthttp.RequestCtx, or a standard context.Context (e.g. the value returned by c.Context() when PassLocalsToContext is enabled). It returns a *jwt.Token from github.com/golang-jwt/jwt/v5.

Config

Property Type Description Default
Next func(fiber.Ctx) bool Defines a function to skip this middleware when it returns true nil
SuccessHandler func(fiber.Ctx) error Executed when a token is valid. c.Next()
ErrorHandler func(fiber.Ctx, error) error ErrorHandler defines a function which is executed for an invalid token. 401 Invalid or expired JWT
SigningKey SigningKey Signing key used to validate the token. Used as a fallback if SigningKeys is empty. nil
SigningKeys map[string]SigningKey Map of signing keys used to validate tokens via the kid header. nil
Claims jwt.Claims Claims are extendable claims data defining token content. jwt.MapClaims{}
Extractor Extractor Function used to extract the token from the request. FromAuthHeader("Bearer")
TokenProcessorFunc func(token string) (string, error) TokenProcessorFunc processes the token extracted using the Extractor. nil
KeyFunc jwt.Keyfunc User-defined function that supplies the public key for token validation. nil (uses internal default)
JWKSetURLs []string List of JSON Web Key (JWK) Set URLs used to obtain signing keys for parsing JWTs. nil

Available Extractors

JWT middleware uses the shared Fiber extractors (github.com/gofiber/fiber/v3/extractors) and provides several helpers for different token sources. Import them with:

import "github.com/gofiber/fiber/v3/extractors"

For an overview and additional examples, see the Fiber Extractors guide:

  • https://docs.gofiber.io/guide/extractors

  • extractors.FromAuthHeader(prefix string) - Extracts token from the Authorization header using the given scheme prefix (e.g., "Bearer"). This is the recommended and most secure method.

  • extractors.FromHeader(header string) - Extracts token from the specified HTTP header

  • extractors.FromQuery(param string) - Extracts token from URL query parameters

  • extractors.FromParam(param string) - Extracts token from URL path parameters

  • extractors.FromCookie(key string) - Extracts token from cookies

  • extractors.FromForm(param string) - Extracts token from form data

  • extractors.Chain(extrs ...extractors.Extractor) - Tries multiple extractors in order until one succeeds

Security Considerations

⚠️ Security Warning: When choosing an extractor, consider the security implications:

  • URL-based extractors (FromQuery, FromParam): Tokens can leak through server logs, browser referrer headers, proxy logs, and browser history. Use only for development or when security is not a primary concern.
  • Form-based extractors (FromForm): Similar risks to URL extractors, especially if forms are submitted via GET requests.
  • Header-based extractors (FromAuthHeader, FromHeader): Most secure as headers are not typically logged or exposed in referrers.
  • Cookie-based extractors (FromCookie): Secure for web applications but requires proper cookie security settings (HttpOnly, Secure, SameSite).

Recommendation: Use FromAuthHeader("Bearer") (the default) for production applications unless you have specific requirements that necessitate alternative extractors.

HS256 Example

package main

import (
 "time"

 "github.com/gofiber/fiber/v3"
 "github.com/gofiber/fiber/v3/extractors"

 jwtware "github.com/gofiber/contrib/v3/jwt"
 "github.com/golang-jwt/jwt/v5"
)

func main() {
 app := fiber.New()

 // Login route
 app.Post("/login", login)

 // Unauthenticated route
 app.Get("/", accessible)

 // JWT Middleware
 app.Use(jwtware.New(jwtware.Config{
  SigningKey: jwtware.SigningKey{Key: []byte("secret")},
  Extractor:  extractors.FromAuthHeader("Bearer"),
 }))

 // Restricted Routes
 app.Get("/restricted", restricted)

 app.Listen(":3000")
}

func login(c fiber.Ctx) error {
 user := c.FormValue("user")
 pass := c.FormValue("pass")

 // Throws Unauthorized error
 if user != "john" || pass != "doe" {
  return c.SendStatus(fiber.StatusUnauthorized)
 }

 // Create the Claims
 claims := jwt.MapClaims{
  "name":  "John Doe",
  "admin": true,
  "exp":   time.Now().Add(time.Hour * 72).Unix(),
 }

 // Create token
 token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

 // Generate encoded token and send it as response.
 t, err := token.SignedString([]byte("secret"))
 if err != nil {
  return c.SendStatus(fiber.StatusInternalServerError)
 }

 return c.JSON(fiber.Map{"token": t})
}

func accessible(c fiber.Ctx) error {
 return c.SendString("Accessible")
}

func restricted(c fiber.Ctx) error {
    user := jwtware.FromContext(c)
    claims := user.Claims.(jwt.MapClaims)
    name := claims["name"].(string)
    return c.SendString("Welcome " + name)
}

package main

import (
 "github.com/gofiber/fiber/v3"

 jwtware "github.com/gofiber/contrib/v3/jwt"
)

func main() {
 app := fiber.New()

 // JWT Middleware with cookie extractor
 app.Use(jwtware.New(jwtware.Config{
  SigningKey: jwtware.SigningKey{Key: []byte("secret")},
  Extractor:  extractors.FromCookie("token"),
 }))

 app.Get("/protected", func(c fiber.Ctx) error {
  return c.SendString("Protected route")
 })

 app.Listen(":3000")
}

HS256 Test

Login using username and password to retrieve a token.

curl --data "user=john&pass=doe" http://localhost:3000/login

Response

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY"
}

Request a restricted resource using the token in Authorization request header.

curl localhost:3000/restricted -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY"

Response

Welcome John Doe

RS256 Example

package main

import (
 "crypto/rand"
 "crypto/rsa"
 "log"
 "time"

 "github.com/gofiber/fiber/v3"

 "github.com/golang-jwt/jwt/v5"

 jwtware "github.com/gofiber/contrib/v3/jwt"
)

var (
 // Obviously, this is just a test example. Do not do this in production.
 // In production, you would have the private key and public key pair generated
 // in advance. NEVER add a private key to any GitHub repo.
 privateKey *rsa.PrivateKey
)

func main() {
 app := fiber.New()

 // Just as a demo, generate a new private/public key pair on each run. See note above.
 rng := rand.Reader
 var err error
 privateKey, err = rsa.GenerateKey(rng, 2048)
 if err != nil {
  log.Fatalf("rsa.GenerateKey: %v", err)
 }

 // Login route
 app.Post("/login", login)

 // Unauthenticated route
 app.Get("/", accessible)

 // JWT Middleware
 app.Use(jwtware.New(jwtware.Config{
  SigningKey: jwtware.SigningKey{
   JWTAlg: jwtware.RS256,
   Key:    privateKey.Public(),
  },
  Extractor: extractors.FromAuthHeader("Bearer"),
 }))

 // Restricted Routes
 app.Get("/restricted", restricted)

 app.Listen(":3000")
}

func login(c fiber.Ctx) error {
 user := c.FormValue("user")
 pass := c.FormValue("pass")

 // Throws Unauthorized error
 if user != "john" || pass != "doe" {
  return c.SendStatus(fiber.StatusUnauthorized)
 }

 // Create the Claims
 claims := jwt.MapClaims{
  "name":  "John Doe",
  "admin": true,
  "exp":   time.Now().Add(time.Hour * 72).Unix(),
 }

 // Create token
 token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)

 // Generate encoded token and send it as response.
 t, err := token.SignedString(privateKey)
 if err != nil {
  log.Printf("token.SignedString: %v", err)
  return c.SendStatus(fiber.StatusInternalServerError)
 }

 return c.JSON(fiber.Map{"token": t})
}

func accessible(c fiber.Ctx) error {
 return c.SendString("Accessible")
}

func restricted(c fiber.Ctx) error {
    user := jwtware.FromContext(c)
    claims := user.Claims.(jwt.MapClaims)
    name := claims["name"].(string)
    return c.SendString("Welcome " + name)
}

Retrieving the token with PassLocalsToContext

When fiber.Config{PassLocalsToContext: true} is set, the JWT token stored by the middleware is also available in the underlying context.Context. Use jwtware.FromContext with any of the supported context types:

// From a fiber.Ctx (most common usage)
token := jwtware.FromContext(c)

// From the underlying context.Context (useful in service layers or when PassLocalsToContext is enabled)
token := jwtware.FromContext(c.Context())

RS256 Test

The RS256 is actually identical to the HS256 test above.

JWK Set Test

The tests are identical to basic JWT tests above, with exception that JWKSetURLs to valid public keys collection in JSON Web Key (JWK) Set format should be supplied. See RFC 7517.

Custom KeyFunc example

KeyFunc defines a user-defined function that supplies the public key for a token validation. The function shall take care of verifying the signing algorithm and selecting the proper key. A user-defined KeyFunc can be useful if tokens are issued by an external party.

When a user-defined KeyFunc is provided, SigningKey, SigningKeys, and SigningMethod are ignored. This is one of the three options to provide a token validation key. The order of precedence is a user-defined KeyFunc, SigningKeys and SigningKey. Required if neither SigningKeys nor SigningKey is provided. Default to an internal implementation verifying the signing algorithm and selecting the proper key.

package main

import (
 "fmt"
  "github.com/gofiber/fiber/v3"

  jwtware "github.com/gofiber/contrib/v3/jwt"
  "github.com/golang-jwt/jwt/v5"
)

func main() {
 app := fiber.New()

 app.Use(jwtware.New(jwtware.Config{
  KeyFunc:   customKeyFunc(),
  Extractor: extractors.FromAuthHeader("Bearer"),
 }))

 app.Get("/ok", func(c fiber.Ctx) error {
  return c.SendString("OK")
 })
}

func customKeyFunc() jwt.Keyfunc {
 return func(t *jwt.Token) (interface{}, error) {
  // Always check the signing method
  if t.Method.Alg() != jwtware.HS256 {
   return nil, fmt.Errorf("Unexpected jwt signing method=%v", t.Header["alg"])
  }

  // TODO custom implementation of loading signing key like from a database
    signingKey := "secret"

  return []byte(signingKey), nil
 }
}

Documentation

Index

Constants

View Source
const (
	// HS256 represents a public cryptography key generated by a 256 bit HMAC algorithm.
	HS256 = "HS256"

	// HS384 represents a public cryptography key generated by a 384 bit HMAC algorithm.
	HS384 = "HS384"

	// HS512 represents a public cryptography key generated by a 512 bit HMAC algorithm.
	HS512 = "HS512"

	// ES256 represents a public cryptography key generated by a 256 bit ECDSA algorithm.
	ES256 = "ES256"

	// ES384 represents a public cryptography key generated by a 384 bit ECDSA algorithm.
	ES384 = "ES384"

	// ES512 represents a public cryptography key generated by a 512 bit ECDSA algorithm.
	ES512 = "ES512"

	// P256 represents a cryptographic elliptical curve type.
	P256 = "P-256"

	// P384 represents a cryptographic elliptical curve type.
	P384 = "P-384"

	// P521 represents a cryptographic elliptical curve type.
	P521 = "P-521"

	// RS256 represents a public cryptography key generated by a 256 bit RSA algorithm.
	RS256 = "RS256"

	// RS384 represents a public cryptography key generated by a 384 bit RSA algorithm.
	RS384 = "RS384"

	// RS512 represents a public cryptography key generated by a 512 bit RSA algorithm.
	RS512 = "RS512"

	// PS256 represents a public cryptography key generated by a 256 bit RSA algorithm.
	PS256 = "PS256"

	// PS384 represents a public cryptography key generated by a 384 bit RSA algorithm.
	PS384 = "PS384"

	// PS512 represents a public cryptography key generated by a 512 bit RSA algorithm.
	PS512 = "PS512"
)

Variables

View Source
var (
	// ErrJWTAlg is returned when the JWT header did not contain the expected algorithm.
	ErrJWTAlg = errors.New("the JWT header did not contain the expected algorithm")

	// ErrMissingToken is returned when no JWT token is found in the request.
	ErrMissingToken = errors.New("missing or malformed JWT")
)

Functions

func FromContext

func FromContext(ctx any) *jwt.Token

FromContext returns the token from the context. It accepts fiber.CustomCtx, fiber.Ctx, *fasthttp.RequestCtx, and context.Context. If there is no token, nil is returned.

func New

func New(config ...Config) fiber.Handler

New ...

Types

type Config

type Config struct {
	// Next defines a function to skip this middleware when returned true.
	//
	// Optional. Default: nil
	Next func(fiber.Ctx) bool

	// SuccessHandler is executed when a token is successfully validated.
	// Optional. Default: nil
	SuccessHandler fiber.Handler

	// ErrorHandler is executed when token validation fails.
	// It allows customization of JWT error responses.
	// Optional. Default: 401 Invalid or expired JWT
	ErrorHandler fiber.ErrorHandler

	// SigningKey is the primary key used to validate tokens.
	// Used as a fallback if SigningKeys is empty.
	// At least one of the following is required: KeyFunc, JWKSetURLs, SigningKeys, or SigningKey.
	SigningKey SigningKey

	// SigningKeys is a map of keys used to validate tokens with the "kid" field.
	// At least one of the following is required: KeyFunc, JWKSetURLs, SigningKeys, or SigningKey.
	SigningKeys map[string]SigningKey

	// Claims are extendable claims data defining token content.
	// Optional. Default value jwt.MapClaims
	Claims jwt.Claims

	// Extractor defines a function to extract the token from the request.
	// Optional. Default: FromAuthHeader("Bearer").
	Extractor extractors.Extractor

	// TokenProcessorFunc processes the token extracted using the Extractor.
	// Optional. Default: nil
	TokenProcessorFunc func(token string) (string, error)

	// KeyFunc provides the public key for JWT verification.
	// It handles algorithm verification and key selection.
	// By default, the github.com/MicahParks/keyfunc/v2 package is used.
	// At least one of the following is required: KeyFunc, JWKSetURLs, SigningKeys, or SigningKey.
	KeyFunc jwt.Keyfunc

	// JWKSetURLs is a list of URLs containing JSON Web Key Sets (JWKS) for signature verification.
	// HTTPS is recommended. The "kid" field in the JWT header and JWKs is mandatory.
	// Default behavior:
	// - Refresh every hour.
	// - Auto-refresh on new "kid" in JWT.
	// - Rate limit refreshes to once every 5 minutes.
	// - Timeout refreshes after 10 seconds.
	// At least one of the following is required: KeyFunc, JWKSetURLs, SigningKeys, or SigningKey.
	JWKSetURLs []string
}

Config defines the config for JWT middleware

type SigningKey

type SigningKey struct {
	// JWTAlg is the algorithm used to sign JWTs. If this value is a non-empty string, this will be checked against the
	// "alg" value in the JWT header.
	//
	// https://www.rfc-editor.org/rfc/rfc7518#section-3.1
	JWTAlg string
	// Key is the cryptographic key used to sign JWTs. For supported types, please see
	// https://github.com/golang-jwt/jwt.
	Key interface{}
}

SigningKey holds information about the recognized cryptographic keys used to sign JWTs by this program.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL