-
-
Notifications
You must be signed in to change notification settings - Fork 964
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: redirect to verification URL even if login_challenge is set (#3412)
Fixes ory/network#320
- Loading branch information
Showing
5 changed files
with
94 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ import ( | |
"github.com/tidwall/gjson" | ||
|
||
"github.com/ory/kratos/driver/config" | ||
"github.com/ory/kratos/hydra" | ||
"github.com/ory/kratos/identity" | ||
"github.com/ory/kratos/internal" | ||
"github.com/ory/kratos/internal/testhelpers" | ||
|
@@ -27,20 +28,23 @@ import ( | |
) | ||
|
||
func TestRegistrationExecutor(t *testing.T) { | ||
t.Parallel() | ||
ctx := context.Background() | ||
for _, strategy := range []string{ | ||
identity.CredentialsTypePassword.String(), | ||
identity.CredentialsTypeOIDC.String(), | ||
identity.CredentialsTypeTOTP.String(), | ||
identity.CredentialsTypeWebAuthn.String(), | ||
} { | ||
|
||
for _, strategy := range identity.AllCredentialTypes { | ||
strategy := strategy.String() | ||
|
||
t.Run("strategy="+strategy, func(t *testing.T) { | ||
t.Parallel() | ||
|
||
conf, reg := internal.NewFastRegistryWithMocks(t) | ||
reg.WithHydra(hydra.NewFake()) | ||
testhelpers.SetDefaultIdentitySchema(conf, "file://./stub/registration.schema.json") | ||
conf.MustSet(ctx, config.ViperKeySelfServiceBrowserDefaultReturnTo, "https://www.ory.sh/") | ||
|
||
newServer := func(t *testing.T, i *identity.Identity, ft flow.Type) *httptest.Server { | ||
newServer := func(t *testing.T, i *identity.Identity, ft flow.Type, flowCallbacks ...func(*registration.Flow)) *httptest.Server { | ||
router := httprouter.New() | ||
|
||
handleErr := testhelpers.SelfServiceHookRegistrationErrorHandler | ||
router.GET("/registration/pre", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { | ||
f, err := registration.NewFlow(conf, time.Minute, x.FakeCSRFToken, r, ft) | ||
|
@@ -54,10 +58,13 @@ func TestRegistrationExecutor(t *testing.T) { | |
if i == nil { | ||
i = testhelpers.SelfServiceHookFakeIdentity(t) | ||
} | ||
a, err := registration.NewFlow(conf, time.Minute, x.FakeCSRFToken, r, ft) | ||
regFlow, err := registration.NewFlow(conf, time.Minute, x.FakeCSRFToken, r, ft) | ||
require.NoError(t, err) | ||
a.RequestURL = x.RequestURL(r).String() | ||
_ = handleErr(t, w, r, reg.RegistrationHookExecutor().PostRegistrationHook(w, r, identity.CredentialsType(strategy), "", a, i)) | ||
regFlow.RequestURL = x.RequestURL(r).String() | ||
for _, callback := range flowCallbacks { | ||
callback(regFlow) | ||
} | ||
_ = handleErr(t, w, r, reg.RegistrationHookExecutor().PostRegistrationHook(w, r, identity.CredentialsType(strategy), "", regFlow, i)) | ||
}) | ||
|
||
ts := httptest.NewServer(router) | ||
|
@@ -161,11 +168,11 @@ func TestRegistrationExecutor(t *testing.T) { | |
assert.Empty(t, gjson.Get(body, "session_token")) | ||
}) | ||
|
||
t.Run("case=should redirect to verification ui if show_verification_ui hook is set", func(t *testing.T) { | ||
t.Run("case=should redirect to verification UI if show_verification_ui hook is set", func(t *testing.T) { | ||
verificationTS := testhelpers.NewVerificationUIFlowEchoServer(t, reg) | ||
t.Cleanup(testhelpers.SelfServiceHookConfigReset(t, conf)) | ||
conf.Set(ctx, config.ViperKeySelfServiceVerificationEnabled, true) | ||
conf.Set(ctx, config.ViperKeySelfServiceRegistrationAfter+".hooks", []map[string]interface{}{ | ||
conf.MustSet(ctx, config.ViperKeySelfServiceVerificationEnabled, true) | ||
conf.MustSet(ctx, config.ViperKeySelfServiceRegistrationAfter+".hooks", []map[string]interface{}{ | ||
{ | ||
"hook": hook.KeyVerificationUI, | ||
}, | ||
|
@@ -179,11 +186,48 @@ func TestRegistrationExecutor(t *testing.T) { | |
assert.NotEmpty(t, res.Request.URL.Query().Get("flow")) | ||
}) | ||
|
||
t.Run("case=should redirect to first verification ui if show_verification_ui hook is set and multiple verifiable addresses", func(t *testing.T) { | ||
t.Run("case=should redirect to verification UI if there is a login_challenge", func(t *testing.T) { | ||
verificationTS := testhelpers.NewVerificationUIFlowEchoServer(t, reg) | ||
t.Cleanup(testhelpers.SelfServiceHookConfigReset(t, conf)) | ||
conf.MustSet(ctx, config.ViperKeySelfServiceVerificationEnabled, true) | ||
conf.MustSet(ctx, config.ViperKeySelfServiceRegistrationAfter+".hooks", []map[string]interface{}{{ | ||
"hook": hook.KeyVerificationUI, | ||
}}) | ||
i := testhelpers.SelfServiceHookFakeIdentity(t) | ||
i.Traits = identity.Traits(`{"email": "[email protected]"}`) | ||
|
||
withOAuthChallenge := func(f *registration.Flow) { | ||
f.OAuth2LoginChallenge = hydra.FakeValidLoginChallenge | ||
} | ||
res, _ := makeRequestPost(t, newServer(t, i, flow.TypeBrowser, withOAuthChallenge), false, url.Values{}) | ||
assert.EqualValues(t, http.StatusOK, res.StatusCode) | ||
assert.Contains(t, res.Request.URL.String(), verificationTS.URL) | ||
assert.NotEmpty(t, res.Request.URL.Query().Get("flow")) | ||
assert.Equal(t, hydra.FakePostLoginURL, res.Request.URL.Query().Get("return_to")) | ||
}) | ||
|
||
t.Run("case=should not redirect to verification UI if the login_challenge is invalid", func(t *testing.T) { | ||
t.Cleanup(testhelpers.SelfServiceHookConfigReset(t, conf)) | ||
conf.MustSet(ctx, config.ViperKeySelfServiceVerificationEnabled, true) | ||
conf.MustSet(ctx, config.ViperKeySelfServiceRegistrationAfter+".hooks", []map[string]interface{}{{ | ||
"hook": hook.KeyVerificationUI, | ||
}}) | ||
i := testhelpers.SelfServiceHookFakeIdentity(t) | ||
i.Traits = identity.Traits(`{"email": "[email protected]"}`) | ||
|
||
withOAuthChallenge := func(f *registration.Flow) { | ||
f.OAuth2LoginChallenge = hydra.FakeInvalidLoginChallenge | ||
} | ||
res, body := makeRequestPost(t, newServer(t, i, flow.TypeBrowser, withOAuthChallenge), false, url.Values{}) | ||
assert.EqualValues(t, http.StatusInternalServerError, res.StatusCode) | ||
assert.Equal(t, hydra.ErrFakeAcceptLoginRequestFailed.Error(), body, "%s", body) | ||
}) | ||
|
||
t.Run("case=should redirect to first verification UI if show_verification_ui hook is set and multiple verifiable addresses", func(t *testing.T) { | ||
verificationTS := testhelpers.NewVerificationUIFlowEchoServer(t, reg) | ||
t.Cleanup(testhelpers.SelfServiceHookConfigReset(t, conf)) | ||
conf.Set(ctx, config.ViperKeySelfServiceVerificationEnabled, true) | ||
conf.Set(ctx, config.ViperKeySelfServiceRegistrationAfter+".hooks", []map[string]interface{}{ | ||
conf.MustSet(ctx, config.ViperKeySelfServiceVerificationEnabled, true) | ||
conf.MustSet(ctx, config.ViperKeySelfServiceRegistrationAfter+".hooks", []map[string]interface{}{ | ||
{ | ||
"hook": hook.KeyVerificationUI, | ||
}, | ||
|
@@ -202,8 +246,8 @@ func TestRegistrationExecutor(t *testing.T) { | |
t.Run("case=should still sent session if show_verification_ui is set after session hook", func(t *testing.T) { | ||
verificationTS := testhelpers.NewVerificationUIFlowEchoServer(t, reg) | ||
t.Cleanup(testhelpers.SelfServiceHookConfigReset(t, conf)) | ||
conf.Set(ctx, config.ViperKeySelfServiceVerificationEnabled, true) | ||
conf.Set(ctx, config.ViperKeySelfServiceRegistrationAfter+".hooks", []map[string]interface{}{ | ||
conf.MustSet(ctx, config.ViperKeySelfServiceVerificationEnabled, true) | ||
conf.MustSet(ctx, config.ViperKeySelfServiceRegistrationAfter+".hooks", []map[string]interface{}{ | ||
{ | ||
"hook": hook.KeyVerificationUI, | ||
}, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters