{"id":"086543bb47d0b900","repo":"labstack/echo","slug":"echo-key-auth-middleware-requires-a-validator-func","errorCode":null,"errorMessage":"echo key-auth middleware requires a validator function","messagePattern":"echo key-auth middleware requires a validator function","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/key_auth.go","lineNumber":146,"sourceCode":"// KeyAuthWithConfig returns an KeyAuth middleware or panics if configuration is invalid.\n//\n// For first valid key it calls the next handler.\n// For invalid key, it sends \"401 - Unauthorized\" response.\n// For missing key, it sends \"400 - Bad Request\" response.\nfunc KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc {\n\treturn toMiddlewareOrPanic(config)\n}\n\n// ToMiddleware converts KeyAuthConfig to middleware or returns an error for invalid configuration\nfunc (config KeyAuthConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n\tif config.Skipper == nil {\n\t\tconfig.Skipper = DefaultKeyAuthConfig.Skipper\n\t}\n\tif config.KeyLookup == \"\" {\n\t\tconfig.KeyLookup = DefaultKeyAuthConfig.KeyLookup\n\t}\n\tif config.Validator == nil {\n\t\treturn nil, errors.New(\"echo key-auth middleware requires a validator function\")\n\t}\n\n\tlimit := cmp.Or(config.AllowedCheckLimit, 1)\n\n\textractors, cErr := createExtractors(config.KeyLookup, limit)\n\tif cErr != nil {\n\t\treturn nil, fmt.Errorf(\"echo key-auth middleware could not create key extractor: %w\", cErr)\n\t}\n\tif len(extractors) == 0 {\n\t\treturn nil, errors.New(\"echo key-auth middleware could not create extractors from KeyLookup string\")\n\t}\n\n\treturn func(next echo.HandlerFunc) echo.HandlerFunc {\n\t\treturn func(c *echo.Context) error {\n\t\t\tif config.Skipper(c) {\n\t\t\t\treturn next(c)\n\t\t\t}\n","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/middleware/key_auth.go#L128-L164","documentation":"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).","triggerScenarios":"Calling KeyAuthWithConfig(KeyAuthConfig{KeyLookup: \"header:X-Api-Key\"}) without setting Validator, or building a config struct and forgetting the Validator field.","commonSituations":"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.","solutions":["Set config.Validator to a KeyAuthValidator that checks the key using crypto/subtle.ConstantTimeCompare.","Prefer the shorthand KeyAuth(func(c *echo.Context, key string, _ middleware.ExtractorSource) (bool, error) {...}) when you only need a validator.","Wire the validator from your key store (DB, secret manager) at startup so it is never nil.","Use config.ToMiddleware() to surface this as a returned error instead of a startup panic."],"exampleFix":"// before\nm := middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{\n    KeyLookup: \"header:X-Api-Key\",\n})\n// after\nm := middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{\n    KeyLookup: \"header:X-Api-Key\",\n    Validator: func(c *echo.Context, key string, _ middleware.ExtractorSource) (bool, error) {\n        return subtle.ConstantTimeCompare([]byte(key), []byte(validKey)) == 1, nil\n    },\n})","handlingStrategy":"validation","validationCode":"func keyAuthMiddleware(lookup string, v middleware.KeyAuthValidator) (echo.MiddlewareFunc, error) {\n    cfg := middleware.KeyAuthConfig{KeyLookup: lookup, Validator: v}\n    if cfg.Validator == nil {\n        return nil, errors.New(\"KeyAuth requires a Validator\")\n    }\n    return cfg.ToMiddleware()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set Validator (use crypto/subtle.ConstantTimeCompare inside it to prevent timing attacks).","Prefer the KeyAuth(fn) shorthand which makes the validator a required parameter.","Use cfg.ToMiddleware() so a missing validator returns an error instead of panicking."],"tags":["middleware","key-auth","auth","config","panic","security","startup"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}