From d93570d330155c27a9315d1f530a0002a459910a Mon Sep 17 00:00:00 2001 From: hackerman <3372410+aeneasr@users.noreply.github.com> Date: Fri, 19 Jan 2024 11:38:21 +0100 Subject: [PATCH] fix: do not generate CSRF token for api flows (#3704) --- .../strategy/code/strategy_recovery.go | 3 +- .../strategy/code/strategy_recovery_test.go | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/selfservice/strategy/code/strategy_recovery.go b/selfservice/strategy/code/strategy_recovery.go index 2a917f0dcecd..894166a236a2 100644 --- a/selfservice/strategy/code/strategy_recovery.go +++ b/selfservice/strategy/code/strategy_recovery.go @@ -170,7 +170,6 @@ func (s *Strategy) recoveryIssueSession(w http.ResponseWriter, r *http.Request, f.UI.Messages.Clear() f.State = flow.StatePassedChallenge - f.SetCSRFToken(s.deps.CSRFHandler().RegenerateToken(w, r)) f.RecoveredIdentityID = uuid.NullUUID{ UUID: id.ID, Valid: true, @@ -191,6 +190,8 @@ func (s *Strategy) recoveryIssueSession(w http.ResponseWriter, r *http.Request, switch f.Type { case flow.TypeBrowser: + f.SetCSRFToken(s.deps.CSRFHandler().RegenerateToken(w, r)) + if err := s.deps.SessionManager().UpsertAndIssueCookie(ctx, w, r, sess); err != nil { return s.retryRecoveryFlow(w, r, f.Type, RetryWithError(err)) } diff --git a/selfservice/strategy/code/strategy_recovery_test.go b/selfservice/strategy/code/strategy_recovery_test.go index b481a37c8726..29a054c28550 100644 --- a/selfservice/strategy/code/strategy_recovery_test.go +++ b/selfservice/strategy/code/strategy_recovery_test.go @@ -1574,6 +1574,43 @@ func TestRecovery_WithContinueWith(t *testing.T) { } }) + t.Run("description=does not issue csrf cookie when submitting API flow", func(t *testing.T) { + t.Run("type="+RecoveryClientTypeAPI.String(), func(t *testing.T) { + c := new(http.Client) + recoveryEmail := testhelpers.RandomEmail() + _ = createIdentityToRecover(t, reg, recoveryEmail) + + actual := submitRecoveryForm(t, c, RecoveryClientTypeAPI, func(v url.Values) { + v.Set("email", recoveryEmail) + }, http.StatusOK) + + message := testhelpers.CourierExpectMessage(ctx, t, reg, recoveryEmail, "Recover access to your account") + recoveryCode := testhelpers.CourierExpectCodeInMessage(t, message, 1) + + action := gjson.Get(actual, "ui.action").String() + require.NotEmpty(t, action) + + flowId := gjson.Get(actual, "id").String() + require.NotEmpty(t, flowId) + + form := withCSRFToken(t, RecoveryClientTypeAPI, actual, url.Values{ + "code": {recoveryCode}, + }) + + // Now submit the correct code + res, err := c.Post(action, "application/json", bytes.NewBufferString(form)) + require.NoError(t, err) + + assert.Equal(t, http.StatusOK, res.StatusCode) + + assert.Empty(t, res.Header.Get("Set-Cookie")) + + json := ioutilx.MustReadAll(res.Body) + require.NotEmpty(t, gjson.GetBytes(json, "continue_with.#(action==show_settings_ui).flow").String(), "%s", json) + require.NotEmpty(t, gjson.GetBytes(json, "continue_with.#(action==set_ory_session_token).ory_session_token").String(), "%s", json) + }) + }) + t.Run("description=should not be able to use an invalid code", func(t *testing.T) { for _, testCase := range flowTypeCases { t.Run("type="+testCase.ClientType.String(), func(t *testing.T) {