Repository: gofiber/fiber
File: middleware/keyauth/keyauth.go (Go)

Code before:
// MultipleKeySourceLookup creates a CustomKeyLookup function that checks multiple sources until one is found
// Each element should be specified according to the format used in KeyLookup
func MultipleKeySourceLookup(keyLookups []string, authScheme string) (KeyauthKeyLookupFunc, error) {
	subExtractors := map[string]KeyauthKeyLookupFunc{}
	var err error
	for _, keyLookup := range keyLookups {
		subExtractors[keyLookup], err = SingleKeyLookup(keyLookup, authScheme)
		if err != nil {
			return nil, err
		}
	}
	return func(c fiber.Ctx) (string, error) {
		for keyLookup, subExtractor := range subExtractors {
			res, err := subExtractor(c)
			if err == nil && res != "" {
				return res, nil
			}
			if !errors.Is(err, ErrMissingOrMalformedAPIKey) {
				return "", fmt.Errorf("[%s] %w", keyLookup, err)
			}
		}
		return "", ErrMissingOrMalformedAPIKey
	}, nil
}

func SingleKeyLookup(keyLookup, authScheme string) (KeyauthKeyLookupFunc, error) {
	parts := strings.Split(keyLookup, ":")
	if len(parts) <= 1 {
		return nil, fmt.Errorf("invalid keyLookup: %s", keyLookup)
	}
	extractor := keyFromHeader(parts[1], authScheme) // in the event of an invalid prefix, it is interpreted as header:
	switch parts[0] {
	case query:
		extractor = keyFromQuery(parts[1])
	case form:
		extractor = keyFromForm(parts[1])
	case param:
		extractor = keyFromParam(parts[1])
	case cookie:
		extractor = keyFromCookie(parts[1])
	}
	return extractor, nil
}

// keyFromHeader returns a function that extracts api key from the request header.
func keyFromHeader(header, authScheme string) KeyauthKeyLookupFunc {
	return func(c fiber.Ctx) (string, error) {
		auth := c.Get(header)
		l := len(authScheme)
		if len(auth) > 0 && l == 0 {
			return auth, nil

Review comment (security):

```suggestion
func DefaultKeyLookup(keyLookup, authScheme string) (KeyauthKeyLookupFunc, error) {
```

Code after:
// MultipleKeySourceLookup creates a CustomKeyLookup function that checks multiple sources until one is found
// Each element should be specified according to the format used in KeyLookup
func MultipleKeySourceLookup(keyLookups []string, authScheme string) (KeyLookupFunc, error) {
	subExtractors := map[string]KeyLookupFunc{}
	var err error
	for _, keyLookup := range keyLookups {
		subExtractors[keyLookup], err = DefaultKeyLookup(keyLookup, authScheme)
		if err != nil {
			return nil, err
		}
	}
	return func(c fiber.Ctx) (string, error) {
		for keyLookup, subExtractor := range subExtractors {
			res, err := subExtractor(c)
			if err == nil && res != "" {
				return res, nil
			}
			if !errors.Is(err, ErrMissingOrMalformedAPIKey) {
				// Defensive Code - not currently possible to hit
				return "", fmt.Errorf("[%s] %w", keyLookup, err)
			}
		}
		return "", ErrMissingOrMalformedAPIKey
	}, nil
}

func DefaultKeyLookup(keyLookup, authScheme string) (KeyLookupFunc, error) {
	parts := strings.Split(keyLookup, ":")
	if len(parts) <= 1 {
		return nil, fmt.Errorf("invalid keyLookup: %q, expected format 'source:name'", keyLookup)
	}
	extractor := KeyFromHeader(parts[1], authScheme) // in the event of an invalid prefix, it is interpreted as header:
	switch parts[0] {
	case query:
		extractor = KeyFromQuery(parts[1])
	case form:
		extractor = KeyFromForm(parts[1])
	case param:
		extractor = KeyFromParam(parts[1])
	case cookie:
		extractor = KeyFromCookie(parts[1])
	}
	return extractor, nil
}

// keyFromHeader returns a function that extracts api key from the request header.
func KeyFromHeader(header, authScheme string) KeyLookupFunc {
	return func(c fiber.Ctx) (string, error) {
		auth := c.Get(header)
		l := len(authScheme)
		if len(auth) > 0 && l == 0 {