github.com/gofiber/fiber/v2@v2.47.0/docs/api/middleware/keyauth.md (about)

     1  ---
     2  id: keyauth
     3  title: Keyauth
     4  ---
     5  
     6  Key auth middleware provides a key based authentication.
     7  
     8  ## Signatures
     9  
    10  ```go
    11  func New(config ...Config) fiber.Handler
    12  ```
    13  
    14  ## Examples
    15  
    16  ```go
    17  package main
    18  
    19  import (
    20  	"crypto/sha256"
    21  	"crypto/subtle"
    22  	"github.com/gofiber/fiber/v2"
    23  	"github.com/gofiber/fiber/v2/middleware/keyauth"
    24  )
    25  
    26  var (
    27  	apiKey = "correct horse battery staple"
    28  )
    29  
    30  func validateAPIKey(c *fiber.Ctx, key string) (bool, error) {
    31  	hashedAPIKey := sha256.Sum256([]byte(apiKey))
    32  	hashedKey := sha256.Sum256([]byte(key))
    33  
    34  	if subtle.ConstantTimeCompare(hashedAPIKey[:], hashedKey[:]) == 1 {
    35  		return true, nil
    36  	}
    37  	return false, keyauth.ErrMissingOrMalformedAPIKey
    38  }
    39  
    40  func main() {
    41  	app := fiber.New()
    42  
    43  	// note that the keyauth middleware needs to be defined before the routes are defined!
    44  	app.Use(keyauth.New(keyauth.Config{
    45  		KeyLookup:  "cookie:access_token",
    46  		Validator:  validateAPIKey,
    47  	}))
    48  
    49  		app.Get("/", func(c *fiber.Ctx) error {
    50  		return c.SendString("Successfully authenticated!")
    51  	})
    52  
    53  	app.Listen(":3000")
    54  }
    55  ```
    56  
    57  **Test:**
    58  
    59  ```bash
    60  # No api-key specified -> 400 missing 
    61  curl http://localhost:3000
    62  #> missing or malformed API Key
    63  
    64  curl --cookie "access_token=correct horse battery staple" http://localhost:3000
    65  #> Successfully authenticated!
    66  
    67  curl --cookie "access_token=Clearly A Wrong Key" http://localhost:3000
    68  #>  missing or malformed API Key
    69  ```
    70  
    71  For a more detailed example, see also the [`github.com/gofiber/recipes`](https://github.com/gofiber/recipes) repository and specifically the `fiber-envoy-extauthz` repository and the [`keyauth example`](https://github.com/gofiber/recipes/blob/master/fiber-envoy-extauthz/authz/main.go) code.
    72  
    73  
    74  ### Authenticate only certain endpoints
    75  
    76  If you want to authenticate only certain endpoints, you can use the `Config` of keyauth and apply a filter function (eg. `authFilter`) like so
    77  
    78  ```go
    79  package main
    80  
    81  import (
    82  	"crypto/sha256"
    83  	"crypto/subtle"
    84  	"github.com/gofiber/fiber/v2"
    85  	"github.com/gofiber/fiber/v2/middleware/keyauth"
    86  	"regexp"
    87  	"strings"
    88  )
    89  
    90  var (
    91  	apiKey        = "correct horse battery staple"
    92  	protectedURLs = []*regexp.Regexp{
    93  		regexp.MustCompile("^/authenticated$"),
    94  		regexp.MustCompile("^/auth2$"),
    95  	}
    96  )
    97  
    98  func validateAPIKey(c *fiber.Ctx, key string) (bool, error) {
    99  	hashedAPIKey := sha256.Sum256([]byte(apiKey))
   100  	hashedKey := sha256.Sum256([]byte(key))
   101  
   102  	if subtle.ConstantTimeCompare(hashedAPIKey[:], hashedKey[:]) == 1 {
   103  		return true, nil
   104  	}
   105  	return false, keyauth.ErrMissingOrMalformedAPIKey
   106  }
   107  
   108  func authFilter(c *fiber.Ctx) bool {
   109  	originalURL := strings.ToLower(c.OriginalURL())
   110  
   111  	for _, pattern := range protectedURLs {
   112  		if pattern.MatchString(originalURL) {
   113  			return false
   114  		}
   115  	}
   116  	return true
   117  }
   118  
   119  func main() {
   120  	app := fiber.New()
   121  
   122  	app.Use(keyauth.New(keyauth.Config{
   123  		Next:    authFilter,
   124  		KeyLookup: "cookie:access_token",
   125  		Validator: validateAPIKey,
   126  	}))
   127  
   128  	app.Get("/", func(c *fiber.Ctx) error {
   129  		return c.SendString("Welcome")
   130  	})
   131  	app.Get("/authenticated", func(c *fiber.Ctx) error {
   132  		return c.SendString("Successfully authenticated!")
   133  	})
   134  	app.Get("/auth2", func(c *fiber.Ctx) error {
   135  		return c.SendString("Successfully authenticated 2!")
   136  	})
   137  
   138  	app.Listen(":3000")
   139  }
   140  ```
   141  
   142  Which results in this
   143  
   144  ```bash
   145  # / does not need to be authenticated
   146  curl http://localhost:3000
   147  #> Welcome
   148  
   149  # /authenticated needs to be authenticated
   150  curl --cookie "access_token=correct horse battery staple" http://localhost:3000/authenticated
   151  #> Successfully authenticated!
   152  
   153  # /auth2 needs to be authenticated too
   154  curl --cookie "access_token=correct horse battery staple" http://localhost:3000/auth2
   155  #> Successfully authenticated 2!
   156  ```
   157  
   158  ### Specifying middleware in the handler
   159  
   160  ```go
   161  package main
   162  
   163  import (
   164  	"crypto/sha256"
   165  	"crypto/subtle"
   166  	"github.com/gofiber/fiber/v2"
   167  	"github.com/gofiber/fiber/v2/middleware/keyauth"
   168  )
   169  
   170  const (
   171    apiKey = "my-super-secret-key"
   172  )
   173  
   174  func main() {
   175  	app := fiber.New()
   176  
   177  	authMiddleware := keyauth.New(keyauth.Config{
   178  		Validator:  func(c *fiber.Ctx, key string) (bool, error) {
   179  			hashedAPIKey := sha256.Sum256([]byte(apiKey))
   180  			hashedKey := sha256.Sum256([]byte(key))
   181  
   182  			if subtle.ConstantTimeCompare(hashedAPIKey[:], hashedKey[:]) == 1 {
   183  				return true, nil
   184  			}
   185  			return false, keyauth.ErrMissingOrMalformedAPIKey
   186  		},
   187  	})
   188  
   189  	app.Get("/", func(c *fiber.Ctx) error {
   190  		return c.SendString("Welcome")
   191  	})
   192  
   193  	app.Get("/allowed",  authMiddleware, func(c *fiber.Ctx) error {
   194  		return c.SendString("Successfully authenticated!")
   195  	})
   196  
   197  	app.Listen(":3000")
   198  }
   199  ```
   200  
   201  Which results in this
   202  
   203  ```bash
   204  # / does not need to be authenticated
   205  curl http://localhost:3000
   206  #> Welcome
   207  
   208  # /allowed needs to be authenticated too
   209  curl --header "Authorization: Bearer my-super-secret-key"  http://localhost:3000/allowed
   210  #> Successfully authenticated!
   211  ```
   212  
   213  ## Config
   214  
   215  ```go
   216  // Config defines the config for middleware.
   217  type Config struct {
   218  	// Next defines a function to skip middleware.
   219  	// Optional. Default: nil
   220  	Next func(*fiber.Ctx) bool
   221  
   222  	// SuccessHandler defines a function which is executed for a valid key.
   223  	// Optional. Default: nil
   224  	SuccessHandler fiber.Handler
   225  
   226  	// ErrorHandler defines a function which is executed for an invalid key.
   227  	// It may be used to define a custom error.
   228  	// Optional. Default: 401 Invalid or expired key
   229  	ErrorHandler fiber.ErrorHandler
   230  
   231  	// KeyLookup is a string in the form of "<source>:<name>" that is used
   232  	// to extract key from the request.
   233  	// Optional. Default value "header:Authorization".
   234  	// Possible values:
   235  	// - "header:<name>"
   236  	// - "query:<name>"
   237  	// - "form:<name>"
   238  	// - "param:<name>"
   239  	// - "cookie:<name>"
   240  	KeyLookup string
   241  
   242  	// AuthScheme to be used in the Authorization header.
   243  	// Optional. Default value "Bearer".
   244  	AuthScheme string
   245  
   246  	// Validator is a function to validate key.
   247  	Validator func(*fiber.Ctx, string) (bool, error)
   248  
   249  	// Context key to store the bearertoken from the token into context.
   250  	// Optional. Default: "token".
   251  	ContextKey string
   252  }
   253  ```
   254  
   255  ## Default Config
   256  
   257  ```go
   258  var ConfigDefault = Config{
   259  	SuccessHandler: func(c *fiber.Ctx) error {
   260  		return c.Next()
   261  	},
   262  	ErrorHandler: func(c *fiber.Ctx, err error) error {
   263  		if err == ErrMissingOrMalformedAPIKey {
   264  			return c.Status(fiber.StatusUnauthorized).SendString(err.Error())
   265  		}
   266  		return c.Status(fiber.StatusUnauthorized).SendString("Invalid or expired API Key")
   267  	},
   268  	KeyLookup:  "header:" + fiber.HeaderAuthorization,
   269  	AuthScheme: "Bearer",
   270  	ContextKey: "token",
   271  }
   272  ```