From ef351c94c0e505112168dd54456e71a015b430c5 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Mon, 16 Sep 2024 10:44:08 +0200 Subject: [PATCH 1/2] fix: incorrect append of code credential identifier Closes #4076 --- ...estSchemaExtensionCredentials-case=12.json | 22 ++++ identity/extension_credentials.go | 13 +- identity/extension_credentials_test.go | 112 ++++++++++-------- identity/handler_test.go | 4 +- .../credentials/code-phone-email.schema.json | 18 +++ internal/client-go/go.sum | 1 + 6 files changed, 113 insertions(+), 57 deletions(-) create mode 100644 identity/.snapshots/TestSchemaExtensionCredentials-case=12.json diff --git a/identity/.snapshots/TestSchemaExtensionCredentials-case=12.json b/identity/.snapshots/TestSchemaExtensionCredentials-case=12.json new file mode 100644 index 000000000000..968d3fa35bdd --- /dev/null +++ b/identity/.snapshots/TestSchemaExtensionCredentials-case=12.json @@ -0,0 +1,22 @@ +{ + "type": "code", + "config": { + "addresses": [ + { + "channel": "sms", + "address": "+4917667111638" + }, + { + "channel": "email", + "address": "bar@ory.sh" + }, + { + "channel": "email", + "address": "foo@ory.sh" + } + ] + }, + "version": 0, + "created_at": "0001-01-01T00:00:00Z", + "updated_at": "0001-01-01T00:00:00Z" +} diff --git a/identity/extension_credentials.go b/identity/extension_credentials.go index faae191b89ca..5bbe8fec89db 100644 --- a/identity/extension_credentials.go +++ b/identity/extension_credentials.go @@ -22,9 +22,10 @@ import ( ) type SchemaExtensionCredentials struct { - i *Identity - v map[CredentialsType][]string - l sync.Mutex + i *Identity + v map[CredentialsType][]string + addresses []CredentialsCodeAddress + l sync.Mutex } func NewSchemaExtensionCredentials(i *Identity) *SchemaExtensionCredentials { @@ -86,10 +87,7 @@ func (r *SchemaExtensionCredentials) Run(ctx jsonschema.ValidationContext, s sch } } - if conf.Addresses == nil { - conf.Addresses = []CredentialsCodeAddress{} - } - + conf.Addresses = r.addresses value, err := x.NormalizeIdentifier(fmt.Sprintf("%s", value), string(via)) if err != nil { return &jsonschema.ValidationError{Message: err.Error()} @@ -120,6 +118,7 @@ func (r *SchemaExtensionCredentials) Run(ctx jsonschema.ValidationContext, s sch return item.Address })..., )) + r.addresses = conf.Addresses cred.Identifiers = r.v[CredentialsTypeCodeAuth] cred.Config, err = json.Marshal(conf) diff --git a/identity/extension_credentials_test.go b/identity/extension_credentials_test.go index fd44bde801c8..990037146333 100644 --- a/identity/extension_credentials_test.go +++ b/identity/extension_credentials_test.go @@ -9,6 +9,8 @@ import ( "fmt" "testing" + "github.com/ory/x/sqlxx" + "github.com/ory/x/snapshotx" "github.com/ory/jsonschema/v3" @@ -25,103 +27,117 @@ var ctx = context.Background() func TestSchemaExtensionCredentials(t *testing.T) { for k, tc := range []struct { - expectErr error - schema string - doc string - expect []string - existing *identity.Credentials - ct identity.CredentialsType + expectErr error + schema string + doc string + expectedIdentifiers []string + existing *identity.Credentials + ct identity.CredentialsType }{ { - doc: `{"email":"foo@ory.sh"}`, - schema: "file://./stub/extension/credentials/schema.json", - expect: []string{"foo@ory.sh"}, - ct: identity.CredentialsTypePassword, + doc: `{"email":"foo@ory.sh"}`, + schema: "file://./stub/extension/credentials/schema.json", + expectedIdentifiers: []string{"foo@ory.sh"}, + ct: identity.CredentialsTypePassword, }, { - doc: `{"emails":["foo@ory.sh","foo@ory.sh","bar@ory.sh"], "username": "foobar"}`, - schema: "file://./stub/extension/credentials/multi.schema.json", - expect: []string{"foo@ory.sh", "bar@ory.sh", "foobar"}, - ct: identity.CredentialsTypePassword, + doc: `{"emails":["foo@ory.sh","foo@ory.sh","bar@ory.sh"], "username": "foobar"}`, + schema: "file://./stub/extension/credentials/multi.schema.json", + expectedIdentifiers: []string{"foo@ory.sh", "bar@ory.sh", "foobar"}, + ct: identity.CredentialsTypePassword, }, { - doc: `{"emails":["foo@ory.sh","foo@ory.sh","bar@ory.sh"], "username": "foobar"}`, - schema: "file://./stub/extension/credentials/multi.schema.json", - expect: []string{"foo@ory.sh", "bar@ory.sh"}, - ct: identity.CredentialsTypeWebAuthn, + doc: `{"emails":["foo@ory.sh","foo@ory.sh","bar@ory.sh"], "username": "foobar"}`, + schema: "file://./stub/extension/credentials/multi.schema.json", + expectedIdentifiers: []string{"foo@ory.sh", "bar@ory.sh"}, + ct: identity.CredentialsTypeWebAuthn, }, { - doc: `{"emails":["FOO@ory.sh","bar@ory.sh"], "username": "foobar"}`, - schema: "file://./stub/extension/credentials/multi.schema.json", - expect: []string{"foo@ory.sh", "bar@ory.sh", "foobar"}, + doc: `{"emails":["FOO@ory.sh","bar@ory.sh"], "username": "foobar"}`, + schema: "file://./stub/extension/credentials/multi.schema.json", + expectedIdentifiers: []string{"foo@ory.sh", "bar@ory.sh", "foobar"}, existing: &identity.Credentials{ Identifiers: []string{"not-foo@ory.sh"}, }, ct: identity.CredentialsTypePassword, }, { - doc: `{"email":"foo@ory.sh"}`, - schema: "file://./stub/extension/credentials/webauthn.schema.json", - expect: []string{"foo@ory.sh"}, - ct: identity.CredentialsTypeWebAuthn, + doc: `{"email":"foo@ory.sh"}`, + schema: "file://./stub/extension/credentials/webauthn.schema.json", + expectedIdentifiers: []string{"foo@ory.sh"}, + ct: identity.CredentialsTypeWebAuthn, }, { - doc: `{"email":"FOO@ory.sh"}`, - schema: "file://./stub/extension/credentials/webauthn.schema.json", - expect: []string{"foo@ory.sh"}, + doc: `{"email":"FOO@ory.sh"}`, + schema: "file://./stub/extension/credentials/webauthn.schema.json", + expectedIdentifiers: []string{"foo@ory.sh"}, existing: &identity.Credentials{ Identifiers: []string{"not-foo@ory.sh"}, }, ct: identity.CredentialsTypeWebAuthn, }, { - doc: `{"email":"foo@ory.sh"}`, - schema: "file://./stub/extension/credentials/code.schema.json", - expect: []string{"foo@ory.sh"}, - ct: identity.CredentialsTypeCodeAuth, + doc: `{"email":"foo@ory.sh"}`, + schema: "file://./stub/extension/credentials/code.schema.json", + expectedIdentifiers: []string{"foo@ory.sh"}, + ct: identity.CredentialsTypeCodeAuth, }, { - doc: `{"email":"FOO@ory.sh"}`, - schema: "file://./stub/extension/credentials/code.schema.json", - expect: []string{"foo@ory.sh"}, + doc: `{"email":"FOO@ory.sh"}`, + schema: "file://./stub/extension/credentials/code.schema.json", + expectedIdentifiers: []string{"foo@ory.sh"}, existing: &identity.Credentials{ Identifiers: []string{"not-foo@ory.sh"}, }, ct: identity.CredentialsTypeCodeAuth, }, { - doc: `{"email":"FOO@ory.sh"}`, - schema: "file://./stub/extension/credentials/code.schema.json", - expect: []string{"foo@ory.sh"}, + doc: `{"email":"FOO@ory.sh"}`, + schema: "file://./stub/extension/credentials/code.schema.json", + expectedIdentifiers: []string{"foo@ory.sh"}, existing: &identity.Credentials{ Identifiers: []string{"not-foo@ory.sh", "foo@ory.sh"}, + Config: sqlxx.JSONRawMessage(`{"addresses":[{"channel":"email","address":"not-foo@ory.sh"}]}`), }, ct: identity.CredentialsTypeCodeAuth, }, { - doc: `{"email":"FOO@ory.sh","phone":"+49 176 671 11 638"}`, - schema: "file://./stub/extension/credentials/code-phone-email.schema.json", - expect: []string{"+4917667111638", "foo@ory.sh"}, + doc: `{"email":"FOO@ory.sh","phone":"+49 176 671 11 638"}`, + schema: "file://./stub/extension/credentials/code-phone-email.schema.json", + expectedIdentifiers: []string{"+4917667111638", "foo@ory.sh"}, existing: &identity.Credentials{ Identifiers: []string{"not-foo@ory.sh", "foo@ory.sh"}, + Config: sqlxx.JSONRawMessage(`{"addresses":[{"channel":"email","address":"not-foo@ory.sh"}]}`), }, ct: identity.CredentialsTypeCodeAuth, }, { - doc: `{"email":"FOO@ory.sh","phone":"+49 176 671 11 638"}`, - schema: "file://./stub/extension/credentials/code-phone-email.schema.json", - expect: []string{"+4917667111638", "foo@ory.sh"}, + doc: `{"email":"FOO@ory.sh","phone":"+49 176 671 11 638"}`, + schema: "file://./stub/extension/credentials/code-phone-email.schema.json", + expectedIdentifiers: []string{"+4917667111638", "foo@ory.sh"}, existing: &identity.Credentials{ Identifiers: []string{"not-foo@ory.sh", "foo@ory.sh"}, + Config: sqlxx.JSONRawMessage(`{"addresses":[{"channel":"email","address":"not-foo@ory.sh"}]}`), + }, + ct: identity.CredentialsTypeCodeAuth, + }, + { + doc: `{"email":"FOO@ory.sh","email2":"FOO@ory.sh","phone":"+49 176 671 11 638"}`, + schema: "file://./stub/extension/credentials/code-phone-email.schema.json", + expectedIdentifiers: []string{"+4917667111638", "foo@ory.sh"}, + existing: &identity.Credentials{ + Identifiers: []string{"not-foo@ory.sh", "fOo@ory.sh"}, + Config: sqlxx.JSONRawMessage(`{"addresses":[{"channel":"email","address":"not-foo@ory.sh"}]}`), }, ct: identity.CredentialsTypeCodeAuth, }, { - doc: `{"email":"FOO@ory.sh","email2":"FOO@ory.sh","phone":"+49 176 671 11 638"}`, - schema: "file://./stub/extension/credentials/code-phone-email.schema.json", - expect: []string{"+4917667111638", "foo@ory.sh"}, + doc: `{"email":"FOO@ory.sh","email2":"FOO@ory.sh","email3":"bar@ory.sh","phone":"+49 176 671 11 638"}`, + schema: "file://./stub/extension/credentials/code-phone-email.schema.json", + expectedIdentifiers: []string{"+4917667111638", "foo@ory.sh", "bar@ory.sh"}, existing: &identity.Credentials{ Identifiers: []string{"not-foo@ory.sh", "fOo@ory.sh"}, + Config: sqlxx.JSONRawMessage(`{"addresses":[{"channel":"email","address":"not-foo@ory.sh"}]}`), }, ct: identity.CredentialsTypeCodeAuth, }, @@ -148,7 +164,7 @@ func TestSchemaExtensionCredentials(t *testing.T) { credentials, ok := i.GetCredentials(tc.ct) require.True(t, ok) - assert.ElementsMatch(t, tc.expect, credentials.Identifiers) + assert.ElementsMatch(t, tc.expectedIdentifiers, credentials.Identifiers) snapshotx.SnapshotT(t, credentials, snapshotx.ExceptPaths("identifiers")) }) } diff --git a/identity/handler_test.go b/identity/handler_test.go index d97c2f73fae4..2f6714137411 100644 --- a/identity/handler_test.go +++ b/identity/handler_test.go @@ -762,9 +762,9 @@ func TestHandler(t *testing.T) { t.Run("case=fails all on a bad identity", func(t *testing.T) { // Test setup: we have a list of valid identitiy patches and a list of invalid ones. // Each run adds one invalid patch to the list and sends it to the server. - // --> we expect the server to fail all patches in the list. + // --> we expectedIdentifiers the server to fail all patches in the list. // Finally, we send just the valid patches - // --> we expect the server to succeed all patches in the list. + // --> we expectedIdentifiers the server to succeed all patches in the list. validPatches := []*identity.BatchIdentityPatch{ {Create: validCreateIdentityBody("valid-patch", 0)}, {Create: validCreateIdentityBody("valid-patch", 1)}, diff --git a/identity/stub/extension/credentials/code-phone-email.schema.json b/identity/stub/extension/credentials/code-phone-email.schema.json index 0b8166b9c337..4e51a5a0aae8 100644 --- a/identity/stub/extension/credentials/code-phone-email.schema.json +++ b/identity/stub/extension/credentials/code-phone-email.schema.json @@ -37,6 +37,24 @@ } } }, + "email3": { + "type": "string", + "format": "email", + "ory.sh/kratos": { + "credentials": { + "password": { + "identifier": true + }, + "webauthn": { + "identifier": true + }, + "code": { + "identifier": true, + "via": "email" + } + } + } + }, "phone": { "type": "string", "format": "tel", diff --git a/internal/client-go/go.sum b/internal/client-go/go.sum index c966c8ddfd0d..6cc3f5911d11 100644 --- a/internal/client-go/go.sum +++ b/internal/client-go/go.sum @@ -4,6 +4,7 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From d4465fe16c5524636a76347a877b796220e36054 Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:47:40 +0200 Subject: [PATCH 2/2] chore: synchronize workspaces --- identity/extension_credentials.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/identity/extension_credentials.go b/identity/extension_credentials.go index 5bbe8fec89db..c9e56ab5ee60 100644 --- a/identity/extension_credentials.go +++ b/identity/extension_credentials.go @@ -80,13 +80,6 @@ func (r *SchemaExtensionCredentials) Run(ctx jsonschema.ValidationContext, s sch }) var conf CredentialsCode - if len(cred.Config) > 0 { - // Only decode the config if it is not empty. - if err := json.Unmarshal(cred.Config, &conf); err != nil { - return &jsonschema.ValidationError{Message: "unable to unmarshal identity credentials"} - } - } - conf.Addresses = r.addresses value, err := x.NormalizeIdentifier(fmt.Sprintf("%s", value), string(via)) if err != nil {