github.com/gofiber/fiber/v2@v2.47.0/middleware/keyauth/keyauth.go (about)

     1  // Special thanks to Echo: https://github.com/labstack/echo/blob/master/middleware/key_auth.go
     2  package keyauth
     3  
     4  import (
     5  	"errors"
     6  	"net/url"
     7  	"strings"
     8  
     9  	"github.com/gofiber/fiber/v2"
    10  )
    11  
    12  // When there is no request of the key thrown ErrMissingOrMalformedAPIKey
    13  var ErrMissingOrMalformedAPIKey = errors.New("missing or malformed API Key")
    14  
    15  const (
    16  	query  = "query"
    17  	form   = "form"
    18  	param  = "param"
    19  	cookie = "cookie"
    20  )
    21  
    22  // New creates a new middleware handler
    23  func New(config ...Config) fiber.Handler {
    24  	// Init config
    25  	cfg := configDefault(config...)
    26  
    27  	// Initialize
    28  	parts := strings.Split(cfg.KeyLookup, ":")
    29  	extractor := keyFromHeader(parts[1], cfg.AuthScheme)
    30  	switch parts[0] {
    31  	case query:
    32  		extractor = keyFromQuery(parts[1])
    33  	case form:
    34  		extractor = keyFromForm(parts[1])
    35  	case param:
    36  		extractor = keyFromParam(parts[1])
    37  	case cookie:
    38  		extractor = keyFromCookie(parts[1])
    39  	}
    40  
    41  	// Return middleware handler
    42  	return func(c *fiber.Ctx) error {
    43  		// Filter request to skip middleware
    44  		if cfg.Next != nil && cfg.Next(c) {
    45  			return c.Next()
    46  		}
    47  
    48  		// Extract and verify key
    49  		key, err := extractor(c)
    50  		if err != nil {
    51  			return cfg.ErrorHandler(c, err)
    52  		}
    53  
    54  		valid, err := cfg.Validator(c, key)
    55  
    56  		if err == nil && valid {
    57  			c.Locals(cfg.ContextKey, key)
    58  			return cfg.SuccessHandler(c)
    59  		}
    60  		return cfg.ErrorHandler(c, err)
    61  	}
    62  }
    63  
    64  // keyFromHeader returns a function that extracts api key from the request header.
    65  func keyFromHeader(header, authScheme string) func(c *fiber.Ctx) (string, error) {
    66  	return func(c *fiber.Ctx) (string, error) {
    67  		auth := c.Get(header)
    68  		l := len(authScheme)
    69  		if len(auth) > 0 && l == 0 {
    70  			return auth, nil
    71  		}
    72  		if len(auth) > l+1 && auth[:l] == authScheme {
    73  			return auth[l+1:], nil
    74  		}
    75  		return "", ErrMissingOrMalformedAPIKey
    76  	}
    77  }
    78  
    79  // keyFromQuery returns a function that extracts api key from the query string.
    80  func keyFromQuery(param string) func(c *fiber.Ctx) (string, error) {
    81  	return func(c *fiber.Ctx) (string, error) {
    82  		key := c.Query(param)
    83  		if key == "" {
    84  			return "", ErrMissingOrMalformedAPIKey
    85  		}
    86  		return key, nil
    87  	}
    88  }
    89  
    90  // keyFromForm returns a function that extracts api key from the form.
    91  func keyFromForm(param string) func(c *fiber.Ctx) (string, error) {
    92  	return func(c *fiber.Ctx) (string, error) {
    93  		key := c.FormValue(param)
    94  		if key == "" {
    95  			return "", ErrMissingOrMalformedAPIKey
    96  		}
    97  		return key, nil
    98  	}
    99  }
   100  
   101  // keyFromParam returns a function that extracts api key from the url param string.
   102  func keyFromParam(param string) func(c *fiber.Ctx) (string, error) {
   103  	return func(c *fiber.Ctx) (string, error) {
   104  		key, err := url.PathUnescape(c.Params(param))
   105  		if err != nil {
   106  			return "", ErrMissingOrMalformedAPIKey
   107  		}
   108  		return key, nil
   109  	}
   110  }
   111  
   112  // keyFromCookie returns a function that extracts api key from the named cookie.
   113  func keyFromCookie(name string) func(c *fiber.Ctx) (string, error) {
   114  	return func(c *fiber.Ctx) (string, error) {
   115  		key := c.Cookies(name)
   116  		if key == "" {
   117  			return "", ErrMissingOrMalformedAPIKey
   118  		}
   119  		return key, nil
   120  	}
   121  }