diff --git a/CHANGELOG.md b/CHANGELOG.md index 0800b71b..828930c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ - ⚠️ Prioritized the user submitted non-empty `createData.email` (_it will be unverified_) when creating the PocketBase user during the first OAuth2 auth. +- Load the request info context during password/OAuth2/OTP authentication ([#6402](https://github.com/pocketbase/pocketbase/issues/6402)). + This could be helpful in case you want to target the auth method as part of the MFA and Auth API rules. + For example, to disable MFA for the OAuth2 auth could be expressed as `@request.context != "oauth2"` MFA rule. + (@todo docs) + - Added `$os.stat(file)` JSVM helper ([#6407](https://github.com/pocketbase/pocketbase/discussions/6407)). diff --git a/apis/record_auth_with_oauth2.go b/apis/record_auth_with_oauth2.go index 3b89993e..de0042b9 100644 --- a/apis/record_auth_with_oauth2.go +++ b/apis/record_auth_with_oauth2.go @@ -35,6 +35,8 @@ func recordAuthWithOAuth2(e *core.RequestEvent) error { fallbackAuthRecord = e.Auth } + e.Set(core.RequestEventKeyInfoContext, core.RequestInfoContextOAuth2) + form := new(recordOAuth2LoginForm) form.collection = collection if err = e.BindBody(form); err != nil { diff --git a/apis/record_auth_with_oauth2_test.go b/apis/record_auth_with_oauth2_test.go index 149ca81b..57070b02 100644 --- a/apis/record_auth_with_oauth2_test.go +++ b/apis/record_auth_with_oauth2_test.go @@ -175,6 +175,20 @@ func TestRecordAuthWithOAuth2(t *testing.T) { if err := app.Save(ea); err != nil { t.Fatal(err) } + + // test at least once that the correct request info context is properly loaded + app.OnRecordAuthRequest().BindFunc(func(e *core.RecordAuthRequestEvent) error { + info, err := e.RequestInfo() + if err != nil { + t.Fatal(err) + } + + if info.Context != core.RequestInfoContextOAuth2 { + t.Fatalf("Expected request context %q, got %q", core.RequestInfoContextOAuth2, info.Context) + } + + return e.Next() + }) }, ExpectedStatus: 200, ExpectedContent: []string{ diff --git a/apis/record_auth_with_otp.go b/apis/record_auth_with_otp.go index 2620dcf5..c4641671 100644 --- a/apis/record_auth_with_otp.go +++ b/apis/record_auth_with_otp.go @@ -26,6 +26,8 @@ func recordAuthWithOTP(e *core.RequestEvent) error { return firstApiError(err, e.BadRequestError("An error occurred while validating the submitted data.", err)) } + e.Set(core.RequestEventKeyInfoContext, core.RequestInfoContextOTP) + event := new(core.RecordAuthWithOTPRequestEvent) event.RequestEvent = e event.Collection = collection diff --git a/apis/record_auth_with_otp_test.go b/apis/record_auth_with_otp_test.go index c312a7a7..c8757d74 100644 --- a/apis/record_auth_with_otp_test.go +++ b/apis/record_auth_with_otp_test.go @@ -269,6 +269,20 @@ func TestRecordAuthWithOTP(t *testing.T) { if err := app.Save(otp); err != nil { t.Fatal(err) } + + // test at least once that the correct request info context is properly loaded + app.OnRecordAuthRequest().BindFunc(func(e *core.RecordAuthRequestEvent) error { + info, err := e.RequestInfo() + if err != nil { + t.Fatal(err) + } + + if info.Context != core.RequestInfoContextOTP { + t.Fatalf("Expected request context %q, got %q", core.RequestInfoContextOTP, info.Context) + } + + return e.Next() + }) }, ExpectedStatus: 200, ExpectedContent: []string{ diff --git a/apis/record_auth_with_password.go b/apis/record_auth_with_password.go index bbf2fc4b..c28f911d 100644 --- a/apis/record_auth_with_password.go +++ b/apis/record_auth_with_password.go @@ -32,6 +32,8 @@ func recordAuthWithPassword(e *core.RequestEvent) error { return firstApiError(err, e.BadRequestError("An error occurred while validating the submitted data.", err)) } + e.Set(core.RequestEventKeyInfoContext, core.RequestInfoContextPasswordAuth) + var foundRecord *core.Record var foundErr error diff --git a/apis/record_auth_with_password_test.go b/apis/record_auth_with_password_test.go index 9cc3fb2b..a2c21b02 100644 --- a/apis/record_auth_with_password_test.go +++ b/apis/record_auth_with_password_test.go @@ -126,6 +126,21 @@ func TestRecordAuthWithPassword(t *testing.T) { "identity":"test@example.com", "password":"1234567890" }`), + BeforeTestFunc: func(t testing.TB, app *tests.TestApp, e *core.ServeEvent) { + // test at least once that the correct request info context is properly loaded + app.OnRecordAuthRequest().BindFunc(func(e *core.RecordAuthRequestEvent) error { + info, err := e.RequestInfo() + if err != nil { + t.Fatal(err) + } + + if info.Context != core.RequestInfoContextPasswordAuth { + t.Fatalf("Expected request context %q, got %q", core.RequestInfoContextPasswordAuth, info.Context) + } + + return e.Next() + }) + }, ExpectedStatus: 200, ExpectedContent: []string{ `"email":"test@example.com"`, diff --git a/core/event_request.go b/core/event_request.go index 4c653953..11a80f7b 100644 --- a/core/event_request.go +++ b/core/event_request.go @@ -154,8 +154,10 @@ const ( RequestInfoContextExpand = "expand" RequestInfoContextRealtime = "realtime" RequestInfoContextProtectedFile = "protectedFile" - RequestInfoContextOAuth2 = "oauth2" RequestInfoContextBatch = "batch" + RequestInfoContextOAuth2 = "oauth2" + RequestInfoContextOTP = "otp" + RequestInfoContextPasswordAuth = "password" ) // RequestInfo defines a HTTP request data struct, usually used