Skip to content

Commit

Permalink
fix: allow using json with form layout in password registration
Browse files Browse the repository at this point in the history
  • Loading branch information
aeneasr committed Aug 25, 2020
1 parent 7c3eb32 commit bd2225c
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 55 deletions.
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -63,7 +63,7 @@ require (
github.com/ory/jsonschema/v3 v3.0.1
github.com/ory/mail/v3 v3.0.0
github.com/ory/viper v1.7.5
github.com/ory/x v0.0.143
github.com/ory/x v0.0.146
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
github.com/pkg/errors v0.9.1
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Expand Up @@ -1085,8 +1085,8 @@ github.com/ory/x v0.0.110/go.mod h1:DJfkE3GdakhshNhw4zlKoRaL/ozg/lcTahA9OCih2BE=
github.com/ory/x v0.0.127 h1:goEspwhiKRoKRMBb6T6nDiv5L2mMU4EQUGwu90WM+Ao=
github.com/ory/x v0.0.127/go.mod h1:FwUujfFuCj5d+xgLn4fGMYPnzriR5bdAIulFXMtnK0M=
github.com/ory/x v0.0.131/go.mod h1:BMzD4kJYW5/GHoBJndjO0lFy7igXz81UfpXzBQplscQ=
github.com/ory/x v0.0.143 h1:pyn6jVklTXnh3lLRfU17m/vVnXHJpD54XKONzuiFQ44=
github.com/ory/x v0.0.143/go.mod h1:9yBcTk55ckN3yoLAfPG38Ne4fl2LZKNACbiRAkXPBUQ=
github.com/ory/x v0.0.146 h1:QCf1w0EJuC+P+4cNO5C6kZViQKMAO517d1iL16nquxc=
github.com/ory/x v0.0.146/go.mod h1:kYT14ajKGfDV8pRPRzQD3begYqRISZq1IQUgOVliQCE=
github.com/parnurzeal/gorequest v0.2.15/go.mod h1:3Kh2QUMJoqw3icWAecsyzkpY7UzRfDhbRdTjtNwNiUE=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
Expand Down
21 changes: 12 additions & 9 deletions selfservice/strategy/password/registration.go
Expand Up @@ -4,12 +4,12 @@ import (
"encoding/json"
"net/http"

"github.com/ory/kratos/driver/configuration"

"github.com/julienschmidt/httprouter"
"github.com/pkg/errors"
"github.com/tidwall/sjson"

"github.com/ory/kratos/driver/configuration"

"github.com/ory/x/errorsx"

_ "github.com/ory/jsonschema/v3/fileloader"
Expand Down Expand Up @@ -71,6 +71,15 @@ func (s *Strategy) handleRegistrationError(w http.ResponseWriter, r *http.Reques
s.d.RegistrationFlowErrorHandler().WriteFlowError(w, r, identity.CredentialsTypePassword, rr, err)
}

func (s *Strategy) decode(p *RegistrationFormPayload, r *http.Request) error {
option, err := s.decoderRegistration()
if err != nil {
return err
}

return s.hd.Decode(r, p, option, decoderx.HTTPDecoderSetValidatePayloads(false), decoderx.HTTPDecoderJSONFollowsFormFormat())
}

func (s *Strategy) decoderRegistration() (decoderx.HTTPDecoderOption, error) {
raw, err := sjson.SetBytes(registrationSchema, "properties.traits.$ref", s.c.DefaultIdentityTraitsSchemaURL().String()+"#/properties/traits")
if err != nil {
Expand Down Expand Up @@ -137,13 +146,7 @@ func (s *Strategy) handleRegistration(w http.ResponseWriter, r *http.Request, _
}

var p RegistrationFormPayload
option, err := s.decoderRegistration()
if err != nil {
s.handleRegistrationError(w, r, ar, nil, err)
return
}

if err := s.hd.Decode(r, &p, option, decoderx.HTTPDecoderSetValidatePayloads(false)); err != nil {
if err := s.decode(&p, r); err != nil {
s.handleRegistrationError(w, r, ar, &p, err)
return
}
Expand Down
58 changes: 15 additions & 43 deletions selfservice/strategy/password/registration_test.go
Expand Up @@ -151,7 +151,7 @@ func TestRegistration(t *testing.T) {
rr, body, res := run(t, true)
assert.Contains(t, res.Request.URL.String(), publicTS.URL+password.RouteRegistration)
assert.Equal(t, rr.ID.String(), gjson.GetBytes(body, "id").String(), "%s", body)
assert.Contains(t, string(body), `cannot unmarshal number`)
assert.Contains(t, string(body), `Expected JSON sent in request body to be an object but got: Number`)
})

t.Run("type=browser", func(t *testing.T) {
Expand Down Expand Up @@ -216,11 +216,9 @@ func TestRegistration(t *testing.T) {
assert.Contains(t, gjson.GetBytes(body, "methods.password.config.fields.#(name==password).messages.0").String(), "data breaches and must no longer be used.", "%s", body)
return res
}

t.Run("type=api", func(t *testing.T) {
res := run(t, true, x.MustEncodeJSON(t, &password.RegistrationFormPayload{
Password: "password",
Traits: []byte(`{"foobar":"bar","username":"registration-identifier-4"}`),
}))
res := run(t, true, `{"password":"password","traits.foobar":"bar","traits.username":"registration-identifier-4"}`)
assert.Contains(t, res.Request.URL.String(), publicTS.URL+password.RouteRegistration)
})

Expand All @@ -246,10 +244,7 @@ func TestRegistration(t *testing.T) {
}

t.Run("type=api", func(t *testing.T) {
res := run(t, true, x.MustEncodeJSON(t, &password.RegistrationFormPayload{
Password: x.NewUUID().String(),
Traits: []byte(`{"username":"registration-identifier-5"}`),
}))
res := run(t, true, `{"password":"c0a5af7a-fa32-4fe1-85b9-3beb4a127164","traits.username":"registration-identifier-5"}`)
assert.Contains(t, res.Request.URL.String(), publicTS.URL+password.RouteRegistration)
})

Expand All @@ -270,10 +265,7 @@ func TestRegistration(t *testing.T) {
}

t.Run("type=api", func(t *testing.T) {
body, res := run(t, true, x.MustEncodeJSON(t, &password.RegistrationFormPayload{
Password: x.NewUUID().String(),
Traits: []byte(`{"username":"registration-identifier-6","foobar":"bar"}`),
}))
body, res := run(t, true, `{"password":"c0a5af7a-fa32-4fe1-85b9-3beb4a127164","traits.username":"registration-identifier-6","traits.foobar":"bar"}`)
assert.Contains(t, res.Request.URL.String(), publicTS.URL+password.RouteRegistration)
assert.Equal(t, int64(http.StatusInternalServerError), gjson.GetBytes(body, "error.code").Int(), "%s", body)
assert.Equal(t, "Internal Server Error", gjson.GetBytes(body, "error.status").String(), "%s", body)
Expand Down Expand Up @@ -301,11 +293,9 @@ func TestRegistration(t *testing.T) {
body, res := makeRequest(t, rr.ID, isAPI, payload, expectStatusCode(isAPI, http.StatusInternalServerError))
return body, res
}

t.Run("type=api", func(t *testing.T) {
body, res := run(t, true, x.MustEncodeJSON(t, &password.RegistrationFormPayload{
Password: x.NewUUID().String(),
Traits: []byte(`{"username":"registration-identifier-7","foobar":"bar"}`),
}))
body, res := run(t, true, `{"password":"c0a5af7a-fa32-4fe1-85b9-3beb4a127164","traits.username":"registration-identifier-7","traits.foobar":"bar"}`)
assert.Contains(t, res.Request.URL.String(), publicTS.URL+password.RouteRegistration)
assert.Equal(t, int64(http.StatusInternalServerError), gjson.GetBytes(body, "error.code").Int(), "%s", body)
assert.Equal(t, "Internal Server Error", gjson.GetBytes(body, "error.status").String(), "%s", body)
Expand Down Expand Up @@ -338,10 +328,7 @@ func TestRegistration(t *testing.T) {
}

t.Run("type=api", func(t *testing.T) {
body, res := run(t, true, x.MustEncodeJSON(t, &password.RegistrationFormPayload{
Password: x.NewUUID().String(),
Traits: []byte(`{"username":"registration-identifier-8-api","foobar":"bar"}`),
}))
body, res := run(t, true, `{"password":"c0a5af7a-fa32-4fe1-85b9-3beb4a127164","traits.username":"registration-identifier-8-api","traits.foobar":"bar"}`)
assert.Contains(t, res.Request.URL.String(), publicTS.URL+password.RouteRegistration)
assert.Equal(t, `registration-identifier-8-api`, gjson.GetBytes(body, "identity.traits.username").String(), "%s", body)
assert.NotEmpty(t, gjson.GetBytes(body, "session_token").String(), "%s", body)
Expand All @@ -368,15 +355,9 @@ func TestRegistration(t *testing.T) {
}

t.Run("type=api", func(t *testing.T) {
_, _ = run(t, true, x.MustEncodeJSON(t, &password.RegistrationFormPayload{
Password: x.NewUUID().String(),
Traits: []byte(`{"username":"registration-identifier-8-api-duplicate","foobar":"bar"}`),
}), http.StatusOK)

body, res := run(t, true, x.MustEncodeJSON(t, &password.RegistrationFormPayload{
Password: x.NewUUID().String(),
Traits: []byte(`{"username":"registration-identifier-8-api-duplicate","foobar":"bar"}`),
}), http.StatusBadRequest)
_, _ = run(t, true, `{"password":"c0a5af7a-fa32-4fe1-85b9-3beb4a127164","traits.username":"registration-identifier-8-api-duplicate","traits.foobar":"bar"}`,http.StatusOK)

body, res := run(t, true, `{"password":"c0a5af7a-fa32-4fe1-85b9-3beb4a127164","traits.username":"registration-identifier-8-api-duplicate","traits.foobar":"bar"}`,http.StatusBadRequest)
assert.Contains(t, res.Request.URL.String(), publicTS.URL+password.RouteRegistration)
assert.Contains(t, gjson.GetBytes(body, "methods.password.config.messages.0.text").String(), "An account with the same identifier (email, phone, username, ...) exists already.", "%s", body)
})
Expand Down Expand Up @@ -448,10 +429,7 @@ func TestRegistration(t *testing.T) {
}

t.Run("type=api", func(t *testing.T) {
res := run(t, true, x.MustEncodeJSON(t, &password.RegistrationFormPayload{
Password: x.NewUUID().String(),
Traits: []byte(`{"username":"registration-identifier-9"}`),
}))
res := run(t, true, `{"password":"c0a5af7a-fa32-4fe1-85b9-3beb4a127164","traits.username":"registration-identifier-9"}`)
assert.Contains(t, res.Request.URL.String(), publicTS.URL+password.RouteRegistration)
})

Expand All @@ -476,10 +454,7 @@ func TestRegistration(t *testing.T) {
}

t.Run("type=api", func(t *testing.T) {
body, res := run(t, true, x.MustEncodeJSON(t, &password.RegistrationFormPayload{
Password: "93172388957812344432",
Traits: []byte(`{"username":"registration-identifier-10-api","foobar":"bar"}`),
}))
body, res := run(t, true, `{"password":"93172388957812344432","traits.username":"registration-identifier-10-api","traits.foobar":"bar"}`)
assert.Contains(t, res.Request.URL.String(), publicTS.URL+password.RouteRegistration)
assert.Equal(t, `registration-identifier-10-api`, gjson.GetBytes(body, "identity.traits.username").String(), "%s", body)
})
Expand All @@ -502,10 +477,7 @@ func TestRegistration(t *testing.T) {
[]configuration.SelfServiceHook{{Name: "session"}})

t.Run("type=api", func(t *testing.T) {
payload := x.MustEncodeJSON(t, &password.RegistrationFormPayload{
Password: "O(lf<ys87LÖ:(h<dsjfl",
Traits: []byte(`{"username":"registration-identifier-11-api","foobar":"bar"}`),
})
payload := `{"password":"O(lf<ys87LÖ:(h<dsjfl","traits.username":"registration-identifier-11","traits.foobar":"bar"}`

body1, res1 := makeRequest(t, newRegistrationRequest(t, time.Minute, true).ID,
true, payload, http.StatusOK)
Expand Down Expand Up @@ -562,7 +534,7 @@ func TestRegistration(t *testing.T) {
Config: &registration.FlowMethodConfig{
FlowMethodConfigurator: &password.RequestMethod{
HTMLForm: &form.HTMLForm{
Action: "https://foo" + password.RouteRegistration + "?request=" + sr.ID.String(),
Action: "https://foo" + password.RouteRegistration + "?flow=" + sr.ID.String(),
Method: "POST",
Fields: form.Fields{
{
Expand Down

0 comments on commit bd2225c

Please sign in to comment.