Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 35 additions & 19 deletions docs/middleware/keyauth.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,36 +223,52 @@ curl --header "Authorization: Bearer my-super-secret-key" http://localhost:3000

## Key Extractors

The middleware extracts the API key from the request using an `Extractor`. You can specify one or more extractors in the configuration.
KeyAuth uses an `Extractor` from the shared [extractors](../guide/extractors) package to retrieve the API key from the request. You can specify one or more extractors in the configuration. For a full list of extractors, chaining, and advanced usage, see the [Extractors Guide](../guide/extractors).

### Built-in Extractors
### Typical Usage

The following extractors are available:
Specify the extractor in the config. For example, to extract from a cookie:

- `keyauth.FromHeader(header string)`: Extracts the key from the specified header.
- `keyauth.FromAuthHeader(header, authScheme string)`: Extracts the key from an authorization header (e.g., `Authorization: Bearer <key>`).
- `keyauth.FromQuery(param string)`: Extracts the key from a URL query parameter.
- `keyauth.FromParam(param string)`: Extracts the key from a URL path parameter.
- `keyauth.FromCookie(name string)`: Extracts the key from a cookie.
- `keyauth.FromForm(name string)`: Extracts the key from a form field.
```go
app.Use(keyauth.New(keyauth.Config{
Extractor: extractors.FromCookie("access_token"),
Validator: validateAPIKey,
}))
```

### Chaining Extractors
To use the default (Authorization header with Bearer scheme):

```go
app.Use(keyauth.New(keyauth.Config{
Validator: validateAPIKey, // Extractor defaults to FromAuthHeader("Bearer")
}))
```

You can use `keyauth.Chain` to try multiple extractors until one succeeds. The first successful extraction is used.
To try multiple sources (header, then query):

```go
// This will try to extract the key from:
// 1. The "X-API-Key" header
// 2. The "api_key" query parameter
app.Use(keyauth.New(keyauth.Config{
Extractor: keyauth.Chain(
keyauth.FromHeader("X-API-Key"),
keyauth.FromQuery("api_key"),
Extractor: extractors.Chain(
extractors.FromHeader("X-API-Key"),
extractors.FromQuery("api_key"),
),
Validator: validateAPIKey,
}))
```

For custom logic, use `extractors.FromCustom`:

```go
app.Use(keyauth.New(keyauth.Config{
Extractor: extractors.FromCustom(func(c fiber.Ctx) (string, error) {
return c.Get("X-My-API-Key"), nil
}),
Validator: validateAPIKey,
}))
```

Refer to the [Extractors Guide](../guide/extractors) for details, security notes, and advanced configuration.

## Config

| Property | Type | Description | Default |
Expand All @@ -261,7 +277,7 @@ app.Use(keyauth.New(keyauth.Config{
| SuccessHandler | `fiber.Handler` | SuccessHandler defines a function which is executed for a valid key. | `c.Next()` |
| ErrorHandler | `fiber.ErrorHandler` | ErrorHandler defines a function which is executed for an invalid key. By default a 401 response with a `WWW-Authenticate` challenge is sent. | Default error handler |
| Validator | `func(fiber.Ctx, string) (bool, error)` | **Required.** Validator is a function to validate the key. | `nil` (panic) |
| Extractor | `keyauth.Extractor` | Extractor defines how to retrieve the key from the request. Use helper functions like `keyauth.FromAuthHeader` or `keyauth.FromCookie`. | `keyauth.FromAuthHeader("Authorization", "Bearer")` |
| Extractor | `extractors.Extractor` | Extractor defines how to retrieve the key from the request. Use helper functions from the shared extractors package, e.g. `extractors.FromAuthHeader("Bearer")` or `extractors.FromCookie("access_token")`. | `extractors.FromAuthHeader("Bearer")` |
| Realm | `string` | Realm specifies the protected area name used in the `WWW-Authenticate` header. | `"Restricted"` |
| Challenge | `string` | Value of the `WWW-Authenticate` header when no `Authorization` scheme is present. | `ApiKey realm="Restricted"` |
| Error | `string` | Error code appended as the `error` parameter in Bearer challenges. Must be `invalid_request`, `invalid_token`, or `insufficient_scope`. | `""` |
Expand All @@ -280,6 +296,6 @@ var ConfigDefault = Config{
return c.Status(fiber.StatusUnauthorized).SendString(ErrMissingOrMalformedAPIKey.Error())
},
Realm: "Restricted",
Extractor: FromAuthHeader(fiber.HeaderAuthorization, "Bearer"),
Extractor: extractors.FromAuthHeader("Bearer"),
}
```
7 changes: 4 additions & 3 deletions middleware/keyauth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/extractors"
)

const (
Expand Down Expand Up @@ -81,8 +82,8 @@ type Config struct {

// Extractor is a function to extract the key from the request.
//
// Optional. Default: FromAuthHeader("Authorization", "Bearer")
Extractor Extractor
// Optional. Default: extractors.FromAuthHeader("Bearer")
Extractor extractors.Extractor
}

// ConfigDefault is the default config
Expand All @@ -94,7 +95,7 @@ var ConfigDefault = Config{
return c.Status(fiber.StatusUnauthorized).SendString(ErrMissingOrMalformedAPIKey.Error())
},
Realm: "Restricted",
Extractor: FromAuthHeader(fiber.HeaderAuthorization, "Bearer"),
Extractor: extractors.FromAuthHeader("Bearer"),
}

// configDefault is a helper function to set default values
Expand Down
3 changes: 2 additions & 1 deletion middleware/keyauth/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/extractors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -49,7 +50,7 @@ func Test_KeyAuth_ConfigDefault_CustomConfig(t *testing.T) {
successHandler := func(c fiber.Ctx) error { return c.SendStatus(fiber.StatusOK) }
errorHandler := func(c fiber.Ctx, _ error) error { return c.SendStatus(fiber.StatusForbidden) }
validator := func(_ fiber.Ctx, _ string) (bool, error) { return true, nil }
extractor := FromHeader("X-API-Key")
extractor := extractors.FromHeader("X-API-Key")

cfg := configDefault(Config{
Next: nextFunc,
Expand Down
Loading
Loading