From bc72525013466bc6b8bb367cea74cd4bc455e421 Mon Sep 17 00:00:00 2001 From: Gani Georgiev Date: Sat, 14 Feb 2026 11:19:13 +0200 Subject: [PATCH] [#7525] made Bearer prefix case-insensitive --- CHANGELOG.md | 5 +++++ apis/middlewares.go | 10 ++++++---- apis/middlewares_test.go | 16 ++++++++++++++++ tests/api.go | 3 ++- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8eeac65a..27287ad6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## v0.36.4 (WIP) + +- Made the optional `Bearer` token prefix case-insensitive ([#7525](https://github.com/pocketbase/pocketbase/pull/7525); thanks @benjamesfleming). + + ## v0.36.3 - Added `Accept-Encoding: identity` to the S3 requests per the suggestion in [#7523](https://github.com/pocketbase/pocketbase/issues/7523). diff --git a/apis/middlewares.go b/apis/middlewares.go index 6f4424d7..dc1d44c3 100644 --- a/apis/middlewares.go +++ b/apis/middlewares.go @@ -207,11 +207,13 @@ func loadAuthToken() *hook.Handler[*core.RequestEvent] { func getAuthTokenFromRequest(e *core.RequestEvent) string { token := e.Request.Header.Get("Authorization") - if token != "" { - // the schema prefix is not required and it is only for - // compatibility with the defaults of some HTTP clients - token = strings.TrimPrefix(token, "Bearer ") + + // the "Bearer" schema prefix is not required by PocketBase and it is + // supported only for compatibility with the defaults of some HTTP clients + if len(token) > 7 && strings.EqualFold(token[:7], "Bearer ") { + return token[7:] } + return token } diff --git a/apis/middlewares_test.go b/apis/middlewares_test.go index d28c1364..2a54afe8 100644 --- a/apis/middlewares_test.go +++ b/apis/middlewares_test.go @@ -224,6 +224,22 @@ func TestRequireAuth(t *testing.T) { ExpectedStatus: 200, ExpectedContent: []string{"test123"}, }, + { + Name: "valid record auth token with Bearer case-insensitive prefix", + Method: http.MethodGet, + URL: "/my/test", + Headers: map[string]string{ + // regular user + "Authorization": "BeArEr eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjRxMXhsY2xtZmxva3UzMyIsInR5cGUiOiJhdXRoIiwiY29sbGVjdGlvbklkIjoiX3BiX3VzZXJzX2F1dGhfIiwiZXhwIjoyNTI0NjA0NDYxLCJyZWZyZXNoYWJsZSI6dHJ1ZX0.ZT3F0Z3iM-xbGgSG3LEKiEzHrPHr8t8IuHLZGGNuxLo", + }, + BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) { + e.Router.GET("/my/test", func(e *core.RequestEvent) error { + return e.String(200, "test123") + }).Bind(apis.RequireAuth()) + }, + ExpectedStatus: 200, + ExpectedContent: []string{"test123"}, + }, } for _, scenario := range scenarios { diff --git a/tests/api.go b/tests/api.go index 35d2928d..43b820a2 100644 --- a/tests/api.go +++ b/tests/api.go @@ -232,7 +232,8 @@ func (scenario *ApiScenario) test(t testing.TB) { // set scenario headers for k, v := range scenario.Headers { - req.Header.Set(k, v) + // trim whitespaces for consistency with the net/http request parsing + req.Header.Set(k, strings.TrimSpace(v)) } // execute request