labstack/echo · error

echo key-auth middleware requires a validator function

Error message

echo key-auth middleware requires a validator function

What it means

Returned by KeyAuthConfig.ToMiddleware when config.Validator is nil. The Validator is the only way the middleware can decide whether an extracted key is valid, so omitting it makes the middleware meaningless. The Validator is also where constant-time comparison must happen to prevent timing attacks (see KeyAuthValidator docs).

Source

Thrown at middleware/key_auth.go:146

// KeyAuthWithConfig returns an KeyAuth middleware or panics if configuration is invalid.
//
// For first valid key it calls the next handler.
// For invalid key, it sends "401 - Unauthorized" response.
// For missing key, it sends "400 - Bad Request" response.
func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc {
	return toMiddlewareOrPanic(config)
}

// ToMiddleware converts KeyAuthConfig to middleware or returns an error for invalid configuration
func (config KeyAuthConfig) ToMiddleware() (echo.MiddlewareFunc, error) {
	if config.Skipper == nil {
		config.Skipper = DefaultKeyAuthConfig.Skipper
	}
	if config.KeyLookup == "" {
		config.KeyLookup = DefaultKeyAuthConfig.KeyLookup
	}
	if config.Validator == nil {
		return nil, errors.New("echo key-auth middleware requires a validator function")
	}

	limit := cmp.Or(config.AllowedCheckLimit, 1)

	extractors, cErr := createExtractors(config.KeyLookup, limit)
	if cErr != nil {
		return nil, fmt.Errorf("echo key-auth middleware could not create key extractor: %w", cErr)
	}
	if len(extractors) == 0 {
		return nil, errors.New("echo key-auth middleware could not create extractors from KeyLookup string")
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c *echo.Context) error {
			if config.Skipper(c) {
				return next(c)
			}

View on GitHub (pinned to 05489dc173)

Solutions

  1. Set config.Validator to a KeyAuthValidator that checks the key using crypto/subtle.ConstantTimeCompare.
  2. Prefer the shorthand KeyAuth(func(c *echo.Context, key string, _ middleware.ExtractorSource) (bool, error) {...}) when you only need a validator.
  3. Wire the validator from your key store (DB, secret manager) at startup so it is never nil.
  4. Use config.ToMiddleware() to surface this as a returned error instead of a startup panic.

Example fix

// before
m := middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{
    KeyLookup: "header:X-Api-Key",
})
// after
m := middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{
    KeyLookup: "header:X-Api-Key",
    Validator: func(c *echo.Context, key string, _ middleware.ExtractorSource) (bool, error) {
        return subtle.ConstantTimeCompare([]byte(key), []byte(validKey)) == 1, nil
    },
})
Defensive patterns

Strategy: validation

Validate before calling

func keyAuthMiddleware(lookup string, v middleware.KeyAuthValidator) (echo.MiddlewareFunc, error) {
    cfg := middleware.KeyAuthConfig{KeyLookup: lookup, Validator: v}
    if cfg.Validator == nil {
        return nil, errors.New("KeyAuth requires a Validator")
    }
    return cfg.ToMiddleware()
}

Prevention

When it happens

Trigger: Calling KeyAuthWithConfig(KeyAuthConfig{KeyLookup: "header:X-Api-Key"}) without setting Validator, or building a config struct and forgetting the Validator field.

Common situations: Developer uses the WithConfig form to customize KeyLookup but forgets Validator; or copies a config and deletes the validator while refactoring. The shorthand KeyAuth(fn) makes this hard to hit because the function is a required argument.

Related errors


AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04). Data as JSON: /data/errors/086543bb47d0b900.json. Report an issue: GitHub.