Skip to content

Commit 06339a4

Browse files
authored
Merge branch 'main' into codex/2025-08-13-15-47-17
2 parents 5ecc8aa + 8f2c4e2 commit 06339a4

File tree

15 files changed

+922
-360
lines changed

15 files changed

+922
-360
lines changed

.github/workflows/benchmark.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
uses: actions/setup-go@v5
3232
with:
3333
# NOTE: Keep this in sync with the version from go.mod
34-
go-version: "1.24.x"
34+
go-version: "1.25.x"
3535

3636
- name: Run Benchmark
3737
run: set -o pipefail; go test ./... -benchmem -run=^$ -bench . | tee output.txt

.github/workflows/linter.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
- uses: actions/setup-go@v5
3030
with:
3131
# NOTE: Keep this in sync with the version from go.mod
32-
go-version: "1.24.x"
32+
go-version: "1.25.x"
3333
cache: false
3434

3535
- name: golangci-lint

.github/workflows/modernize.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
- uses: actions/setup-go@v5
2828
with:
2929
# NOTE: Keep this in sync with the version from go.mod
30-
go-version: "1.24.x"
30+
go-version: "1.25.x"
3131
cache: false
3232

3333
- name: modernize

.github/workflows/test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
unit:
1616
strategy:
1717
matrix:
18-
go-version: [1.24.x]
18+
go-version: [1.25.x]
1919
platform: [ubuntu-latest, windows-latest, macos-latest, macos-13]
2020
runs-on: ${{ matrix.platform }}
2121
steps:
@@ -31,7 +31,7 @@ jobs:
3131
run: go run gotest.tools/gotestsum@latest -f testname -- ./... -race -count=1 -coverprofile=coverage.txt -covermode=atomic -shuffle=on
3232

3333
- name: Upload coverage reports to Codecov
34-
if: ${{ matrix.platform == 'ubuntu-latest' && matrix.go-version == '1.24.x' }}
34+
if: ${{ matrix.platform == 'ubuntu-latest' && matrix.go-version == '1.25.x' }}
3535
uses: codecov/[email protected]
3636
with:
3737
token: ${{ secrets.CODECOV_TOKEN }}

docs/intro.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ These docs are for **Fiber v3**, which was released on **Month xx, 202x**.
1212

1313
### Installation
1414

15-
First, [download](https://go.dev/dl/) and install Go. Version `1.24` or higher is required.
15+
First, [download](https://go.dev/dl/) and install Go. Version `1.25` or higher is required.
1616

1717
Installation is done using the [`go get`](https://pkg.go.dev/cmd/go/#hdr-Add_dependencies_to_current_module_and_install_them) command:
1818

docs/middleware/encryptcookie.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ To generate a 32 char key, use `openssl rand -base64 32` or `encryptcookie.Gener
6767
|:----------|:----------------------------------------------------|:------------------------------------------------------------------------------------------------------|:-----------------------------|
6868
| Next | `func(fiber.Ctx) bool` | A function to skip this middleware when returned true. | `nil` |
6969
| Except | `[]string` | Array of cookie keys that should not be encrypted. | `[]` |
70-
| Key | `string` | A base64-encoded unique key to encode & decode cookies. Required. Key length should be 32 characters. | (No default, required field) |
70+
| Key | `string` | A base64-encoded unique key to encode & decode cookies. Required. Key length should be 16, 24, or 32 bytes. | (No default, required field) |
7171
| Encryptor | `func(decryptedString, key string) (string, error)` | A custom function to encrypt cookies. | `EncryptCookie` |
7272
| Decryptor | `func(encryptedString, key string) (string, error)` | A custom function to decrypt cookies. | `DecryptCookie` |
7373

@@ -95,7 +95,7 @@ app.Use(encryptcookie.New(encryptcookie.Config{
9595
Except: []string{csrf.ConfigDefault.CookieName}, // exclude CSRF cookie
9696
}))
9797
app.Use(csrf.New(csrf.Config{
98-
KeyLookup: "header:" + csrf.HeaderName,
98+
Extractor: csrf.FromHeader(csrf.HeaderName),
9999
CookieSameSite: "Lax",
100100
CookieSecure: true,
101101
CookieHTTPOnly: false,

docs/middleware/keyauth.md

Lines changed: 72 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ func TokenFromContext(c fiber.Ctx) string
1515

1616
## Examples
1717

18+
### Basic Example
19+
20+
This example shows how to use the KeyAuth middleware with an API key passed in a cookie.
21+
1822
```go
1923
package main
2024

@@ -44,7 +48,7 @@ func main() {
4448

4549
// note that the keyauth middleware needs to be defined before the routes are defined!
4650
app.Use(keyauth.New(keyauth.Config{
47-
KeyLookup: "cookie:access_token",
51+
Extractor: keyauth.FromCookie("access_token"),
4852
Validator: validateAPIKey,
4953
}))
5054

@@ -56,25 +60,27 @@ func main() {
5660
}
5761
```
5862

59-
## Test
63+
**Test:**
6064

6165
```bash
62-
# No api-key specified -> 400 missing
66+
# No api-key specified -> 401 missing api key in cookie
6367
curl http://localhost:3000
64-
#> missing or malformed API Key
68+
#> missing api key in cookie
6569

70+
# Correct API key -> 200 OK
6671
curl --cookie "access_token=correct horse battery staple" http://localhost:3000
6772
#> Successfully authenticated!
6873

74+
# Incorrect API key -> 401 Invalid or expired API Key
6975
curl --cookie "access_token=Clearly A Wrong Key" http://localhost:3000
70-
#> missing or malformed API Key
76+
#> Invalid or expired API Key
7177
```
7278

7379
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.
7480

7581
### Authenticate only certain endpoints
7682

77-
If you want to authenticate only certain endpoints, you can use the `Config` of keyauth and apply a filter function (eg. `authFilter`) like so
83+
If you want to authenticate only certain endpoints, you can use the `Next` function in the config to skip the middleware for specific routes.
7884

7985
```go
8086
package main
@@ -111,18 +117,20 @@ func authFilter(c fiber.Ctx) bool {
111117

112118
for _, pattern := range protectedURLs {
113119
if pattern.MatchString(originalURL) {
120+
// Run middleware for protected routes
114121
return false
115122
}
116123
}
124+
// Skip middleware for non-protected routes
117125
return true
118126
}
119127

120128
func main() {
121129
app := fiber.New()
122130

123131
app.Use(keyauth.New(keyauth.Config{
124-
Next: authFilter,
125-
KeyLookup: "cookie:access_token",
132+
Next: authFilter,
133+
Extractor: keyauth.FromCookie("access_token"),
126134
Validator: validateAPIKey,
127135
}))
128136

@@ -140,7 +148,7 @@ func main() {
140148
}
141149
```
142150

143-
Which results in this
151+
**Test:**
144152

145153
```bash
146154
# / does not need to be authenticated
@@ -158,6 +166,8 @@ curl --cookie "access_token=correct horse battery staple" http://localhost:3000/
158166

159167
### Specifying middleware in the handler
160168

169+
You can apply the middleware to specific routes or groups instead of globally. This example uses the default extractor (`FromAuthHeader`).
170+
161171
```go
162172
package main
163173

@@ -199,30 +209,60 @@ func main() {
199209
}
200210
```
201211

202-
Which results in this
212+
**Test:**
203213

204214
```bash
205215
# / does not need to be authenticated
206216
curl http://localhost:3000
207217
#> Welcome
208218

209-
# /allowed needs to be authenticated too
219+
# /allowed needs to be authenticated
210220
curl --header "Authorization: Bearer my-super-secret-key" http://localhost:3000/allowed
211221
#> Successfully authenticated!
212222
```
213223

224+
## Key Extractors
225+
226+
The middleware extracts the API key from the request using an `Extractor`. You can specify one or more extractors in the configuration.
227+
228+
### Built-in Extractors
229+
230+
The following extractors are available:
231+
232+
- `keyauth.FromHeader(header string)`: Extracts the key from the specified header.
233+
- `keyauth.FromAuthHeader(header, authScheme string)`: Extracts the key from an authorization header (e.g., `Authorization: Bearer <key>`).
234+
- `keyauth.FromQuery(param string)`: Extracts the key from a URL query parameter.
235+
- `keyauth.FromParam(param string)`: Extracts the key from a URL path parameter.
236+
- `keyauth.FromCookie(name string)`: Extracts the key from a cookie.
237+
- `keyauth.FromForm(name string)`: Extracts the key from a form field.
238+
239+
### Chaining Extractors
240+
241+
You can use `keyauth.Chain` to try multiple extractors in order until one succeeds. The first successful extraction will be used.
242+
243+
```go
244+
// This will try to extract the key from:
245+
// 1. The "X-API-Key" header
246+
// 2. The "api_key" query parameter
247+
app.Use(keyauth.New(keyauth.Config{
248+
Extractor: keyauth.Chain(
249+
keyauth.FromHeader("X-API-Key"),
250+
keyauth.FromQuery("api_key"),
251+
),
252+
Validator: validateAPIKey,
253+
}))
254+
```
255+
214256
## Config
215257

216258
| Property | Type | Description | Default |
217259
|:----------------|:-----------------------------------------|:-------------------------------------------------------------------------------------------------------|:------------------------------|
218260
| Next | `func(fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
219-
| SuccessHandler | `fiber.Handler` | SuccessHandler defines a function which is executed for a valid key. | `nil` |
220-
| 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. | `nil` |
221-
| KeyLookup | `string` | KeyLookup is a string in the form of "`<source>:<name>`" that is used to extract the key from the request. | "header:Authorization" |
222-
| CustomKeyLookup | `KeyLookupFunc` aka `func(c fiber.Ctx) (string, error)` | If more complex logic is required to extract the key from the request, an arbitrary function to extract it can be specified here. Utility helper functions are described below. | `nil` |
223-
| AuthScheme | `string` | AuthScheme to be used with the `Authorization` header. When `KeyLookup` is not set, this defaults to `"Bearer"`. | "Bearer" |
261+
| SuccessHandler | `fiber.Handler` | SuccessHandler defines a function which is executed for a valid key. | `c.Next()` |
262+
| 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 |
263+
| Validator | `func(fiber.Ctx, string) (bool, error)` | **Required.** Validator is a function to validate the key. | `nil` (panic) |
264+
| 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")` |
224265
| Realm | `string` | Realm specifies the protected area name used in the `WWW-Authenticate` header. | `"Restricted"` |
225-
| Validator | `func(fiber.Ctx, string) (bool, error)` | Validator is a function to validate the key. | A function for key validation |
226266

227267
## Default Config
228268

@@ -231,17 +271,20 @@ var ConfigDefault = Config{
231271
SuccessHandler: func(c fiber.Ctx) error {
232272
return c.Next()
233273
},
234-
ErrorHandler: nil,
235-
KeyLookup: "header:" + fiber.HeaderAuthorization,
236-
CustomKeyLookup: nil,
237-
AuthScheme: "Bearer",
238-
Realm: "Restricted",
274+
ErrorHandler: func(c fiber.Ctx, err error) error {
275+
switch {
276+
case errors.Is(err, ErrMissingOrMalformedAPIKey),
277+
errors.Is(err, ErrMissingAPIKey),
278+
errors.Is(err, ErrMissingAPIKeyInHeader),
279+
errors.Is(err, ErrMissingAPIKeyInQuery),
280+
errors.Is(err, ErrMissingAPIKeyInParam),
281+
errors.Is(err, ErrMissingAPIKeyInForm),
282+
errors.Is(err, ErrMissingAPIKeyInCookie):
283+
return c.Status(fiber.StatusUnauthorized).SendString(err.Error())
284+
}
285+
return c.Status(fiber.StatusUnauthorized).SendString("Invalid or expired API Key")
286+
},
287+
Realm: "Restricted",
288+
Extractor: FromAuthHeader(fiber.HeaderAuthorization, "Bearer"),
239289
}
240290
```
241-
242-
## CustomKeyLookup
243-
244-
Two public utility functions are provided that may be useful when creating custom extraction:
245-
246-
* `DefaultKeyLookup(keyLookup string, authScheme string)`: This is the function that implements the default `KeyLookup` behavior, exposed to be used as a component of custom parsing logic
247-
* `MultipleKeySourceLookup(keyLookups []string, authScheme string)`: Creates a CustomKeyLookup function that checks each listed source using the above function until a key is found or the options are all exhausted. For example, `MultipleKeySourceLookup([]string{"header:Authorization", "header:x-api-key", "cookie:apikey"}, "Bearer")` would first check the standard Authorization header, checks the `x-api-key` header next, and finally checks for a cookie named `apikey`. If any of these contain a valid API key, the request continues. Otherwise, an error is returned.

docs/whats_new.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Here's a quick overview of the changes in Fiber `v3`:
4848

4949
## Drop for old Go versions
5050

51-
Fiber `v3` drops support for Go versions below `1.24`. We recommend upgrading to Go `1.24` or higher to use Fiber `v3`.
51+
Fiber `v3` drops support for Go versions below `1.25`. We recommend upgrading to Go `1.25` or higher to use Fiber `v3`.
5252

5353
## 🚀 App
5454

@@ -1093,7 +1093,7 @@ The `Expiration` field in the CSRF middleware configuration has been renamed to
10931093

10941094
### EncryptCookie
10951095

1096-
Added support for specifying Key length when using `encryptcookie.GenerateKey(length)`. This allows the user to generate keys compatible with `AES-128`, `AES-192`, and `AES-256` (Default).
1096+
Added support for specifying key length when using `encryptcookie.GenerateKey(length)`. Keys must be base64-encoded and may be 16, 24, or 32 bytes when decoded, supporting AES-128, AES-192, and AES-256 (default).
10971097

10981098
### EnvVar
10991099

@@ -1113,6 +1113,7 @@ Refer to the [healthcheck middleware migration guide](./middleware/healthcheck.m
11131113
### KeyAuth
11141114

11151115
The keyauth middleware was updated to introduce a configurable `Realm` field for the `WWW-Authenticate` header.
1116+
The old string-based `KeyLookup` configuration has been replaced with an `Extractor` field. Use helper functions like `keyauth.FromHeader`, `keyauth.FromAuthHeader`, or `keyauth.FromCookie` to define where the key should be retrieved from. Multiple sources can be combined with `keyauth.Chain`. See the migration guide below.
11161117

11171118
### Logger
11181119

@@ -1938,6 +1939,28 @@ Passwords configured for BasicAuth must now be pre-hashed. If no prefix is suppl
19381939
You can also set the optional `HeaderLimit` and `Charset`
19391940
options to further control authentication behavior.
19401941
1942+
#### KeyAuth
1943+
1944+
The keyauth middleware was updated to introduce a configurable `Realm` field for the `WWW-Authenticate` header.
1945+
The old string-based `KeyLookup` configuration has been replaced with an `Extractor` field, and the `AuthScheme` field has been removed. The auth scheme is now inferred from the extractor used (e.g., `keyauth.FromAuthHeader`). Use helper functions like `keyauth.FromHeader`, `keyauth.FromAuthHeader`, or `keyauth.FromCookie` to define where the key should be retrieved from. Multiple sources can be combined with `keyauth.Chain`.
1946+
1947+
```go
1948+
// Before
1949+
app.Use(keyauth.New(keyauth.Config{
1950+
KeyLookup: "header:Authorization",
1951+
AuthScheme: "Bearer",
1952+
Validator: validateAPIKey,
1953+
}))
1954+
1955+
// After
1956+
app.Use(keyauth.New(keyauth.Config{
1957+
Extractor: keyauth.FromAuthHeader(fiber.HeaderAuthorization, "Bearer"),
1958+
Validator: validateAPIKey,
1959+
}))
1960+
```
1961+
1962+
Combine multiple sources with `keyauth.Chain()` when needed.
1963+
19411964
#### Cache
19421965
19431966
The deprecated `Store` and `Key` fields were removed. Use `Storage` and

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/gofiber/fiber/v3
22

3-
go 1.24.0
3+
go 1.25.0
44

55
require (
66
github.com/gofiber/schema v1.6.0

0 commit comments

Comments
 (0)