diff --git a/.gitignore b/.gitignore index 6525a0dcfb9b..d91c2fb7d111 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ cover.out .idea/ tmp/ +ddl/ .DS_Store /kratos packrd/ diff --git a/.grype.yaml b/.grype.yaml index 4621efcfbc3c..d9727bf1ecf9 100644 --- a/.grype.yaml +++ b/.grype.yaml @@ -3,3 +3,4 @@ ignore: - vulnerability: CVE-2015-5237 - vulnerability: CVE-2022-30065 - vulnerability: CVE-2023-2650 + - vulnerability: CVE-2023-4813 \ No newline at end of file diff --git a/cmd/identities/get_test.go b/cmd/identities/get_test.go index b8f09e7f039f..eafe31520828 100644 --- a/cmd/identities/get_test.go +++ b/cmd/identities/get_test.go @@ -79,6 +79,7 @@ func TestGetCmd(t *testing.T) { InitialAccessToken: transform(accessToken + "0"), InitialRefreshToken: transform(refreshToken + "0"), InitialIDToken: transform(idToken + "0"), + Organization: "foo-org-id", }, { Subject: "baz", @@ -86,6 +87,7 @@ func TestGetCmd(t *testing.T) { InitialAccessToken: transform(accessToken + "1"), InitialRefreshToken: transform(refreshToken + "1"), InitialIDToken: transform(idToken + "1"), + Organization: "bar-org-id", }, }}), } diff --git a/driver/registry.go b/driver/registry.go index e0e0d2562393..3040951d9726 100644 --- a/driver/registry.go +++ b/driver/registry.go @@ -180,11 +180,13 @@ func NewRegistryFromDSN(ctx context.Context, c *config.Config, l *logrusx.Logger } type options struct { - skipNetworkInit bool - config *config.Config - replaceTracer func(*otelx.Tracer) *otelx.Tracer - inspect func(Registry) error - extraMigrations []fs.FS + skipNetworkInit bool + config *config.Config + replaceTracer func(*otelx.Tracer) *otelx.Tracer + inspect func(Registry) error + extraMigrations []fs.FS + replacementStrategies []NewStrategy + extraHooks map[string]func(config.SelfServiceHook) any } type RegistryOption func(*options) @@ -205,6 +207,23 @@ func ReplaceTracer(f func(*otelx.Tracer) *otelx.Tracer) RegistryOption { } } +type NewStrategy func(deps any) any + +// WithReplaceStrategies adds a strategy to the registry. This is useful if you want to +// add a custom strategy to the registry. Default strategies with the same +// name/ID will be overwritten. +func WithReplaceStrategies(s ...NewStrategy) RegistryOption { + return func(o *options) { + o.replacementStrategies = append(o.replacementStrategies, s...) + } +} + +func WithExtraHooks(hooks map[string]func(config.SelfServiceHook) any) RegistryOption { + return func(o *options) { + o.extraHooks = hooks + } +} + func Inspect(f func(reg Registry) error) RegistryOption { return func(o *options) { o.inspect = f diff --git a/driver/registry_default.go b/driver/registry_default.go index b4733fc6dccf..68c460e5297c 100644 --- a/driver/registry_default.go +++ b/driver/registry_default.go @@ -78,7 +78,7 @@ import ( "github.com/ory/kratos/driver/config" "github.com/ory/kratos/identity" "github.com/ory/kratos/selfservice/errorx" - password2 "github.com/ory/kratos/selfservice/strategy/password" + "github.com/ory/kratos/selfservice/strategy/password" "github.com/ory/kratos/session" ) @@ -123,7 +123,7 @@ type RegistryDefault struct { sessionTokenizer *session.Tokenizer passwordHasher hash.Hasher - passwordValidator password2.Validator + passwordValidator password.Validator crypter cipher.Cipher @@ -157,7 +157,8 @@ type RegistryDefault struct { selfserviceLogoutHandler *logout.Handler - selfserviceStrategies []interface{} + selfserviceStrategies []any + replacementSelfserviceStrategies []NewStrategy hydra hydra.Hydra @@ -317,17 +318,25 @@ func (m *RegistryDefault) CourierConfig() config.CourierConfigs { return m.Config() } -func (m *RegistryDefault) selfServiceStrategies() []interface{} { +func (m *RegistryDefault) selfServiceStrategies() []any { if len(m.selfserviceStrategies) == 0 { - m.selfserviceStrategies = []interface{}{ - password2.NewStrategy(m), - oidc.NewStrategy(m), - profile.NewStrategy(m), - code.NewStrategy(m), - link.NewStrategy(m), - totp.NewStrategy(m), - webauthn.NewStrategy(m), - lookup.NewStrategy(m), + if m.replacementSelfserviceStrategies != nil { + // Construct self-service strategies from the replacements + for _, newStrategy := range m.replacementSelfserviceStrategies { + m.selfserviceStrategies = append(m.selfserviceStrategies, newStrategy(m)) + } + } else { + // Construct the default list of strategies + m.selfserviceStrategies = []any{ + password.NewStrategy(m), + oidc.NewStrategy(m), + profile.NewStrategy(m), + code.NewStrategy(m), + link.NewStrategy(m), + totp.NewStrategy(m), + webauthn.NewStrategy(m), + lookup.NewStrategy(m), + } } } @@ -352,9 +361,15 @@ func (m *RegistryDefault) strategyLoginEnabled(ctx context.Context, id string) b } } -func (m *RegistryDefault) RegistrationStrategies(ctx context.Context) (registrationStrategies registration.Strategies) { +func (m *RegistryDefault) RegistrationStrategies(ctx context.Context, filters ...registration.StrategyFilter) (registrationStrategies registration.Strategies) { +nextStrategy: for _, strategy := range m.selfServiceStrategies() { if s, ok := strategy.(registration.Strategy); ok { + for _, filter := range filters { + if !filter(s) { + continue nextStrategy + } + } if m.strategyRegistrationEnabled(ctx, s.ID().String()) { registrationStrategies = append(registrationStrategies, s) } @@ -374,9 +389,15 @@ func (m *RegistryDefault) AllRegistrationStrategies() registration.Strategies { return registrationStrategies } -func (m *RegistryDefault) LoginStrategies(ctx context.Context) (loginStrategies login.Strategies) { +func (m *RegistryDefault) LoginStrategies(ctx context.Context, filters ...login.StrategyFilter) (loginStrategies login.Strategies) { +nextStrategy: for _, strategy := range m.selfServiceStrategies() { if s, ok := strategy.(login.Strategy); ok { + for _, filter := range filters { + if !filter(s) { + continue nextStrategy + } + } if m.strategyLoginEnabled(ctx, s.ID().String()) { loginStrategies = append(loginStrategies, s) } @@ -495,10 +516,10 @@ func (m *RegistryDefault) Hasher(ctx context.Context) hash.Hasher { return m.passwordHasher } -func (m *RegistryDefault) PasswordValidator() password2.Validator { +func (m *RegistryDefault) PasswordValidator() password.Validator { if m.passwordValidator == nil { var err error - m.passwordValidator, err = password2.NewDefaultPasswordValidatorStrategy(m) + m.passwordValidator, err = password.NewDefaultPasswordValidatorStrategy(m) if err != nil { m.Logger().WithError(err).Fatal("could not initialize DefaultPasswordValidator") } @@ -622,6 +643,14 @@ func (m *RegistryDefault) Init(ctx context.Context, ctxer contextx.Contextualize m.trc = o.replaceTracer(m.trc) } + if o.replacementStrategies != nil { + m.replacementSelfserviceStrategies = o.replacementStrategies + } + + if o.extraHooks != nil { + m.WithHooks(o.extraHooks) + } + bc := backoff.NewExponentialBackOff() bc.MaxElapsedTime = time.Minute * 5 bc.Reset() diff --git a/embedx/config.schema.json b/embedx/config.schema.json index 5ad71652f665..02f568ee71fe 100644 --- a/embedx/config.schema.json +++ b/embedx/config.schema.json @@ -96,6 +96,23 @@ "hook" ] }, + "b2bSSOHook": { + "type": "object", + "properties": { + "hook": { + "const": "b2b_sso" + }, + "config": { + "type": "object", + "additionalProperties": true + } + }, + "additionalProperties": false, + "required": [ + "hook", + "config" + ] + }, "webHookAuthBasicAuthProperties": { "properties": { "type": { @@ -578,6 +595,14 @@ }, "requested_claims": { "$ref": "#/definitions/OIDCClaims" + }, + "organization_id": { + "title": "Organization ID", + "description": "The ID of the organization that this provider belongs to. Only effective in the Ory Network.", + "type": "string", + "examples": [ + "12345678-1234-1234-1234-123456789012" + ] } }, "additionalProperties": false, @@ -699,6 +724,9 @@ "anyOf": [ { "$ref": "#/definitions/selfServiceWebHook" + }, + { + "$ref": "#/definitions/b2bSSOHook" } ] }, @@ -811,6 +839,9 @@ }, { "$ref": "#/definitions/selfServiceRequireVerifiedAddressHook" + }, + { + "$ref": "#/definitions/b2bSSOHook" } ] }, @@ -838,6 +869,9 @@ }, { "$ref": "#/definitions/selfServiceShowVerificationUIHook" + }, + { + "$ref": "#/definitions/b2bSSOHook" } ] }, @@ -932,6 +966,9 @@ }, { "$ref": "#/definitions/selfServiceRequireVerifiedAddressHook" + }, + { + "$ref": "#/definitions/b2bSSOHook" } ] }, @@ -2828,6 +2865,12 @@ } }, "additionalProperties": false + }, + "organizations": { + "title": "Organizations", + "description": "Secifies which organizations are available. Only effective in the Ory Network.", + "type": "array", + "default": [] } }, "allOf": [ diff --git a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_cleartext_password_and_oidc_credentials.json b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_cleartext_password_and_oidc_credentials.json index 9c2afdacbd18..e7074eaf4bd3 100644 --- a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_cleartext_password_and_oidc_credentials.json +++ b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_cleartext_password_and_oidc_credentials.json @@ -38,5 +38,6 @@ "email": "import-2@ory.sh" }, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=SSHA.json b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=SSHA.json index 0b41bd82167b..ed0c80c0e4f7 100644 --- a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=SSHA.json +++ b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=SSHA.json @@ -16,5 +16,6 @@ "email": "import-hash-6@ory.sh" }, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=SSHA256.json b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=SSHA256.json index 03976a0b06ea..ec7baa351d83 100644 --- a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=SSHA256.json +++ b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=SSHA256.json @@ -16,5 +16,6 @@ "email": "import-hash-7@ory.sh" }, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=SSHA512.json b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=SSHA512.json index 202c333f4bee..b07b12075ad7 100644 --- a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=SSHA512.json +++ b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=SSHA512.json @@ -16,5 +16,6 @@ "email": "import-hash-8@ory.sh" }, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=argon2i.json b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=argon2i.json index 6be9d80c32b5..95cf2a91558b 100644 --- a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=argon2i.json +++ b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=argon2i.json @@ -16,5 +16,6 @@ "email": "import-hash-2@ory.sh" }, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=argon2id.json b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=argon2id.json index 4383ba993b6c..d73f67f20863 100644 --- a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=argon2id.json +++ b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=argon2id.json @@ -16,5 +16,6 @@ "email": "import-hash-3@ory.sh" }, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=bcrypt2.json b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=bcrypt2.json index 5ed1aaf1ac95..062ac584f786 100644 --- a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=bcrypt2.json +++ b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=bcrypt2.json @@ -16,5 +16,6 @@ "email": "import-hash-1@ory.sh" }, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=md5.json b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=md5.json index e19627c2a999..d7fb134c7f38 100644 --- a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=md5.json +++ b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=md5.json @@ -16,5 +16,6 @@ "email": "import-hash-5@ory.sh" }, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=pkbdf2.json b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=pkbdf2.json index e3f1b0050810..51cdaa603524 100644 --- a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=pkbdf2.json +++ b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=pkbdf2.json @@ -16,5 +16,6 @@ "email": "import-hash-0@ory.sh" }, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=scrypt.json b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=scrypt.json index 029159b996c9..f8fc83b20016 100644 --- a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=scrypt.json +++ b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-with_hashed_passwords-hash=scrypt.json @@ -16,5 +16,6 @@ "email": "import-hash-4@ory.sh" }, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-without_any_credentials.json b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-without_any_credentials.json index a6faeb36232a..fe341f881564 100644 --- a/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-without_any_credentials.json +++ b/identity/.snapshots/TestHandler-case=should_be_able_to_import_users-without_any_credentials.json @@ -15,5 +15,6 @@ "email": "import-1@ory.sh" }, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_and_multiple_fido_mfa_type-admin.json b/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_and_multiple_fido_mfa_type-admin.json index 2f07be5e9858..f99899936b3e 100644 --- a/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_and_multiple_fido_mfa_type-admin.json +++ b/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_and_multiple_fido_mfa_type-admin.json @@ -39,5 +39,6 @@ "state": "active", "traits": {}, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_and_multiple_fido_mfa_type-public.json b/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_and_multiple_fido_mfa_type-public.json index 2f07be5e9858..f99899936b3e 100644 --- a/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_and_multiple_fido_mfa_type-public.json +++ b/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_and_multiple_fido_mfa_type-public.json @@ -39,5 +39,6 @@ "state": "active", "traits": {}, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_type-admin.json b/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_type-admin.json index e67fb02d62a5..96640c4e5ca9 100644 --- a/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_type-admin.json +++ b/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_type-admin.json @@ -27,5 +27,6 @@ "state": "active", "traits": {}, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_type-public.json b/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_type-public.json index e67fb02d62a5..96640c4e5ca9 100644 --- a/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_type-public.json +++ b/identity/.snapshots/TestHandler-case=should_delete_credential_of_a_specific_user_and_no_longer_be_able_to_retrieve_it-type=remove_webauthn_passwordless_type-public.json @@ -27,5 +27,6 @@ "state": "active", "traits": {}, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_0.json b/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_0.json index 5ade813c32c7..467c98ce96a2 100644 --- a/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_0.json +++ b/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_0.json @@ -11,6 +11,7 @@ "metadata_public": { "public-0": "public" }, + "organization_id": null, "schema_id": "multiple_emails", "state": "active", "traits": { diff --git a/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_1.json b/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_1.json index 9b4723abacf8..9e033a976c95 100644 --- a/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_1.json +++ b/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_1.json @@ -11,6 +11,7 @@ "metadata_public": { "public-1": "public" }, + "organization_id": null, "schema_id": "multiple_emails", "state": "active", "traits": { diff --git a/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_2.json b/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_2.json index 9ff93b942dce..dbb945ee485b 100644 --- a/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_2.json +++ b/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_2.json @@ -11,6 +11,7 @@ "metadata_public": { "public-2": "public" }, + "organization_id": null, "schema_id": "multiple_emails", "state": "active", "traits": { diff --git a/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_3.json b/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_3.json index 49d8da5cc71a..4800666e9aa8 100644 --- a/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_3.json +++ b/identity/.snapshots/TestHandler-suite=PATCH_identities-case=success-assert=identity_3.json @@ -11,6 +11,7 @@ "metadata_public": { "public-3": "public" }, + "organization_id": null, "schema_id": "multiple_emails", "state": "active", "traits": { diff --git a/identity/.snapshots/TestHandler-suite=create_and_update-case=should_get_identity_with_credentials-case=should_get_identity_with_password_and_webauthn_credentials_included.json b/identity/.snapshots/TestHandler-suite=create_and_update-case=should_get_identity_with_credentials-case=should_get_identity_with_password_and_webauthn_credentials_included.json index ae4336a69ff3..c44f358f0573 100644 --- a/identity/.snapshots/TestHandler-suite=create_and_update-case=should_get_identity_with_credentials-case=should_get_identity_with_password_and_webauthn_credentials_included.json +++ b/identity/.snapshots/TestHandler-suite=create_and_update-case=should_get_identity_with_credentials-case=should_get_identity_with_password_and_webauthn_credentials_included.json @@ -36,5 +36,6 @@ "state": "active", "traits": {}, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-suite=create_and_update-case=should_get_identity_with_credentials-case=should_get_identity_with_password_credentials_included.json b/identity/.snapshots/TestHandler-suite=create_and_update-case=should_get_identity_with_credentials-case=should_get_identity_with_password_credentials_included.json index 0004001d98f5..b833a571eaad 100644 --- a/identity/.snapshots/TestHandler-suite=create_and_update-case=should_get_identity_with_credentials-case=should_get_identity_with_password_credentials_included.json +++ b/identity/.snapshots/TestHandler-suite=create_and_update-case=should_get_identity_with_credentials-case=should_get_identity_with_password_credentials_included.json @@ -32,5 +32,6 @@ "state": "active", "traits": {}, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestHandler-suite=create_and_update-case=should_get_identity_with_credentials-case=should_get_identity_without_credentials_included.json b/identity/.snapshots/TestHandler-suite=create_and_update-case=should_get_identity_with_credentials-case=should_get_identity_without_credentials_included.json index 967eec6d8f92..a7840bdb3df9 100644 --- a/identity/.snapshots/TestHandler-suite=create_and_update-case=should_get_identity_with_credentials-case=should_get_identity_without_credentials_included.json +++ b/identity/.snapshots/TestHandler-suite=create_and_update-case=should_get_identity_with_credentials-case=should_get_identity_without_credentials_included.json @@ -29,5 +29,6 @@ "state": "active", "traits": {}, "metadata_public": null, - "metadata_admin": null + "metadata_admin": null, + "organization_id": null } diff --git a/identity/.snapshots/TestUpgradeCredentials-empty_credentials.json b/identity/.snapshots/TestUpgradeCredentials-empty_credentials.json index 8226d7ef009d..81b0c2a4dcab 100644 --- a/identity/.snapshots/TestUpgradeCredentials-empty_credentials.json +++ b/identity/.snapshots/TestUpgradeCredentials-empty_credentials.json @@ -6,5 +6,6 @@ "traits": null, "metadata_public": null, "created_at": "0001-01-01T00:00:00Z", - "updated_at": "0001-01-01T00:00:00Z" + "updated_at": "0001-01-01T00:00:00Z", + "organization_id": null } diff --git a/identity/.snapshots/TestUpgradeCredentials-type=webauthn-from=v0.json b/identity/.snapshots/TestUpgradeCredentials-type=webauthn-from=v0.json index 83c81edb6e0c..0236be234d48 100644 --- a/identity/.snapshots/TestUpgradeCredentials-type=webauthn-from=v0.json +++ b/identity/.snapshots/TestUpgradeCredentials-type=webauthn-from=v0.json @@ -48,5 +48,6 @@ "traits": null, "metadata_public": null, "created_at": "0001-01-01T00:00:00Z", - "updated_at": "0001-01-01T00:00:00Z" + "updated_at": "0001-01-01T00:00:00Z", + "organization_id": null } diff --git a/identity/.snapshots/TestUpgradeCredentials-type=webauthn-from=v1.json b/identity/.snapshots/TestUpgradeCredentials-type=webauthn-from=v1.json index 57614f591497..60038539418a 100644 --- a/identity/.snapshots/TestUpgradeCredentials-type=webauthn-from=v1.json +++ b/identity/.snapshots/TestUpgradeCredentials-type=webauthn-from=v1.json @@ -33,5 +33,6 @@ "traits": null, "metadata_public": null, "created_at": "0001-01-01T00:00:00Z", - "updated_at": "0001-01-01T00:00:00Z" + "updated_at": "0001-01-01T00:00:00Z", + "organization_id": null } diff --git a/identity/credentials_oidc.go b/identity/credentials_oidc.go index 1ad0ada209c1..09b5d0aecad0 100644 --- a/identity/credentials_oidc.go +++ b/identity/credentials_oidc.go @@ -29,10 +29,11 @@ type CredentialsOIDCProvider struct { InitialIDToken string `json:"initial_id_token"` InitialAccessToken string `json:"initial_access_token"` InitialRefreshToken string `json:"initial_refresh_token"` + Organization string `json:"organization,omitempty"` } // NewCredentialsOIDC creates a new OIDC credential. -func NewCredentialsOIDC(idToken, accessToken, refreshToken, provider, subject string) (*Credentials, error) { +func NewCredentialsOIDC(idToken, accessToken, refreshToken, provider, subject, organization string) (*Credentials, error) { if provider == "" { return nil, errors.New("received empty provider in oidc credentials") } @@ -50,6 +51,7 @@ func NewCredentialsOIDC(idToken, accessToken, refreshToken, provider, subject st InitialIDToken: idToken, InitialAccessToken: accessToken, InitialRefreshToken: refreshToken, + Organization: organization, }}, }); err != nil { return nil, errors.WithStack(x.PseudoPanic. @@ -66,3 +68,13 @@ func NewCredentialsOIDC(idToken, accessToken, refreshToken, provider, subject st func OIDCUniqueID(provider, subject string) string { return fmt.Sprintf("%s:%s", provider, subject) } + +func (c *CredentialsOIDC) Organization() string { + for _, p := range c.Providers { + if p.Organization != "" { + return p.Organization + } + } + + return "" +} diff --git a/identity/credentials_oidc_test.go b/identity/credentials_oidc_test.go index b916220f1b9b..dda20f73deb7 100644 --- a/identity/credentials_oidc_test.go +++ b/identity/credentials_oidc_test.go @@ -10,10 +10,10 @@ import ( ) func TestNewCredentialsOIDC(t *testing.T) { - _, err := NewCredentialsOIDC("", "", "", "", "not-empty") + _, err := NewCredentialsOIDC("", "", "", "", "not-empty", "") require.Error(t, err) - _, err = NewCredentialsOIDC("", "", "", "not-empty", "") + _, err = NewCredentialsOIDC("", "", "", "not-empty", "", "") require.Error(t, err) - _, err = NewCredentialsOIDC("", "", "", "not-empty", "not-empty") + _, err = NewCredentialsOIDC("", "", "", "not-empty", "not-empty", "") require.NoError(t, err) } diff --git a/identity/identity.go b/identity/identity.go index 070ec30a666d..064c21121fc1 100644 --- a/identity/identity.go +++ b/identity/identity.go @@ -127,8 +127,9 @@ type Identity struct { CreatedAt time.Time `json:"created_at" db:"created_at"` // UpdatedAt is a helper struct field for gobuffalo.pop. - UpdatedAt time.Time `json:"updated_at" db:"updated_at"` - NID uuid.UUID `json:"-" faker:"-" db:"nid"` + UpdatedAt time.Time `json:"updated_at" db:"updated_at"` + NID uuid.UUID `json:"-" faker:"-" db:"nid"` + OrganizationID uuid.NullUUID `json:"organization_id,omitempty" faker:"-" db:"organization_id"` } // Traits represent an identity's traits. The identity is able to create, modify, and delete traits @@ -459,6 +460,11 @@ func (i *Identity) WithDeclassifiedCredentials(ctx context.Context, c cipher.Pro return false } + toPublish.Config, err = sjson.SetBytes(toPublish.Config, fmt.Sprintf("providers.%d.organization", i), v.Get("organization").String()) + if err != nil { + return false + } + i++ return true }) diff --git a/internal/client-go/api_frontend.go b/internal/client-go/api_frontend.go index 657a2c6c7721..0260af5a71b6 100644 --- a/internal/client-go/api_frontend.go +++ b/internal/client-go/api_frontend.go @@ -941,6 +941,7 @@ type FrontendApiApiCreateBrowserLoginFlowRequest struct { returnTo *string cookie *string loginChallenge *string + organization *string } func (r FrontendApiApiCreateBrowserLoginFlowRequest) Refresh(refresh bool) FrontendApiApiCreateBrowserLoginFlowRequest { @@ -963,6 +964,10 @@ func (r FrontendApiApiCreateBrowserLoginFlowRequest) LoginChallenge(loginChallen r.loginChallenge = &loginChallenge return r } +func (r FrontendApiApiCreateBrowserLoginFlowRequest) Organization(organization string) FrontendApiApiCreateBrowserLoginFlowRequest { + r.organization = &organization + return r +} func (r FrontendApiApiCreateBrowserLoginFlowRequest) Execute() (*LoginFlow, *http.Response, error) { return r.ApiService.CreateBrowserLoginFlowExecute(r) @@ -1041,6 +1046,9 @@ func (a *FrontendApiService) CreateBrowserLoginFlowExecute(r FrontendApiApiCreat if r.loginChallenge != nil { localVarQueryParams.Add("login_challenge", parameterToString(*r.loginChallenge, "")) } + if r.organization != nil { + localVarQueryParams.Add("organization", parameterToString(*r.organization, "")) + } // to determine the Content-Type header localVarHTTPContentTypes := []string{} @@ -1414,6 +1422,7 @@ type FrontendApiApiCreateBrowserRegistrationFlowRequest struct { returnTo *string loginChallenge *string afterVerificationReturnTo *string + organization *string } func (r FrontendApiApiCreateBrowserRegistrationFlowRequest) ReturnTo(returnTo string) FrontendApiApiCreateBrowserRegistrationFlowRequest { @@ -1428,6 +1437,10 @@ func (r FrontendApiApiCreateBrowserRegistrationFlowRequest) AfterVerificationRet r.afterVerificationReturnTo = &afterVerificationReturnTo return r } +func (r FrontendApiApiCreateBrowserRegistrationFlowRequest) Organization(organization string) FrontendApiApiCreateBrowserRegistrationFlowRequest { + r.organization = &organization + return r +} func (r FrontendApiApiCreateBrowserRegistrationFlowRequest) Execute() (*RegistrationFlow, *http.Response, error) { return r.ApiService.CreateBrowserRegistrationFlowExecute(r) @@ -1499,6 +1512,9 @@ func (a *FrontendApiService) CreateBrowserRegistrationFlowExecute(r FrontendApiA if r.afterVerificationReturnTo != nil { localVarQueryParams.Add("after_verification_return_to", parameterToString(*r.afterVerificationReturnTo, "")) } + if r.organization != nil { + localVarQueryParams.Add("organization", parameterToString(*r.organization, "")) + } // to determine the Content-Type header localVarHTTPContentTypes := []string{} diff --git a/internal/client-go/model_identity.go b/internal/client-go/model_identity.go index ea9a18b6972b..282821f468ed 100644 --- a/internal/client-go/model_identity.go +++ b/internal/client-go/model_identity.go @@ -27,7 +27,8 @@ type Identity struct { // NullJSONRawMessage represents a json.RawMessage that works well with JSON, SQL, and Swagger and is NULLable- MetadataAdmin interface{} `json:"metadata_admin,omitempty"` // NullJSONRawMessage represents a json.RawMessage that works well with JSON, SQL, and Swagger and is NULLable- - MetadataPublic interface{} `json:"metadata_public,omitempty"` + MetadataPublic interface{} `json:"metadata_public,omitempty"` + OrganizationId NullableString `json:"organization_id,omitempty"` // RecoveryAddresses contains all the addresses that can be used to recover an identity. RecoveryAddresses []RecoveryIdentityAddress `json:"recovery_addresses,omitempty"` // SchemaID is the ID of the JSON Schema to be used for validating the identity's traits. @@ -219,6 +220,49 @@ func (o *Identity) SetMetadataPublic(v interface{}) { o.MetadataPublic = v } +// GetOrganizationId returns the OrganizationId field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *Identity) GetOrganizationId() string { + if o == nil || o.OrganizationId.Get() == nil { + var ret string + return ret + } + return *o.OrganizationId.Get() +} + +// GetOrganizationIdOk returns a tuple with the OrganizationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *Identity) GetOrganizationIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return o.OrganizationId.Get(), o.OrganizationId.IsSet() +} + +// HasOrganizationId returns a boolean if a field has been set. +func (o *Identity) HasOrganizationId() bool { + if o != nil && o.OrganizationId.IsSet() { + return true + } + + return false +} + +// SetOrganizationId gets a reference to the given NullableString and assigns it to the OrganizationId field. +func (o *Identity) SetOrganizationId(v string) { + o.OrganizationId.Set(&v) +} + +// SetOrganizationIdNil sets the value for OrganizationId to be an explicit nil +func (o *Identity) SetOrganizationIdNil() { + o.OrganizationId.Set(nil) +} + +// UnsetOrganizationId ensures that no value is present for OrganizationId, not even an explicit nil +func (o *Identity) UnsetOrganizationId() { + o.OrganizationId.Unset() +} + // GetRecoveryAddresses returns the RecoveryAddresses field value if set, zero value otherwise. func (o *Identity) GetRecoveryAddresses() []RecoveryIdentityAddress { if o == nil || o.RecoveryAddresses == nil { @@ -470,6 +514,9 @@ func (o Identity) MarshalJSON() ([]byte, error) { if o.MetadataPublic != nil { toSerialize["metadata_public"] = o.MetadataPublic } + if o.OrganizationId.IsSet() { + toSerialize["organization_id"] = o.OrganizationId.Get() + } if o.RecoveryAddresses != nil { toSerialize["recovery_addresses"] = o.RecoveryAddresses } diff --git a/internal/client-go/model_identity_credentials_oidc_provider.go b/internal/client-go/model_identity_credentials_oidc_provider.go index b1ce3cead760..f905f2f60413 100644 --- a/internal/client-go/model_identity_credentials_oidc_provider.go +++ b/internal/client-go/model_identity_credentials_oidc_provider.go @@ -20,6 +20,7 @@ type IdentityCredentialsOidcProvider struct { InitialAccessToken *string `json:"initial_access_token,omitempty"` InitialIdToken *string `json:"initial_id_token,omitempty"` InitialRefreshToken *string `json:"initial_refresh_token,omitempty"` + Organization *string `json:"organization,omitempty"` Provider *string `json:"provider,omitempty"` Subject *string `json:"subject,omitempty"` } @@ -137,6 +138,38 @@ func (o *IdentityCredentialsOidcProvider) SetInitialRefreshToken(v string) { o.InitialRefreshToken = &v } +// GetOrganization returns the Organization field value if set, zero value otherwise. +func (o *IdentityCredentialsOidcProvider) GetOrganization() string { + if o == nil || o.Organization == nil { + var ret string + return ret + } + return *o.Organization +} + +// GetOrganizationOk returns a tuple with the Organization field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IdentityCredentialsOidcProvider) GetOrganizationOk() (*string, bool) { + if o == nil || o.Organization == nil { + return nil, false + } + return o.Organization, true +} + +// HasOrganization returns a boolean if a field has been set. +func (o *IdentityCredentialsOidcProvider) HasOrganization() bool { + if o != nil && o.Organization != nil { + return true + } + + return false +} + +// SetOrganization gets a reference to the given string and assigns it to the Organization field. +func (o *IdentityCredentialsOidcProvider) SetOrganization(v string) { + o.Organization = &v +} + // GetProvider returns the Provider field value if set, zero value otherwise. func (o *IdentityCredentialsOidcProvider) GetProvider() string { if o == nil || o.Provider == nil { @@ -212,6 +245,9 @@ func (o IdentityCredentialsOidcProvider) MarshalJSON() ([]byte, error) { if o.InitialRefreshToken != nil { toSerialize["initial_refresh_token"] = o.InitialRefreshToken } + if o.Organization != nil { + toSerialize["organization"] = o.Organization + } if o.Provider != nil { toSerialize["provider"] = o.Provider } diff --git a/internal/client-go/model_login_flow.go b/internal/client-go/model_login_flow.go index dc7c67ea2649..161377f6b680 100644 --- a/internal/client-go/model_login_flow.go +++ b/internal/client-go/model_login_flow.go @@ -30,6 +30,7 @@ type LoginFlow struct { // Ory OAuth 2.0 Login Challenge. This value is set using the `login_challenge` query parameter of the registration and login endpoints. If set will cooperate with Ory OAuth2 and OpenID to act as an OAuth2 server / OpenID Provider. Oauth2LoginChallenge *string `json:"oauth2_login_challenge,omitempty"` Oauth2LoginRequest *OAuth2LoginRequest `json:"oauth2_login_request,omitempty"` + OrganizationId NullableString `json:"organization_id,omitempty"` // Refresh stores whether this login flow should enforce re-authentication. Refresh *bool `json:"refresh,omitempty"` // RequestURL is the initial URL that was requested from Ory Kratos. It can be used to forward information contained in the URL's path or query for example. @@ -272,6 +273,49 @@ func (o *LoginFlow) SetOauth2LoginRequest(v OAuth2LoginRequest) { o.Oauth2LoginRequest = &v } +// GetOrganizationId returns the OrganizationId field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *LoginFlow) GetOrganizationId() string { + if o == nil || o.OrganizationId.Get() == nil { + var ret string + return ret + } + return *o.OrganizationId.Get() +} + +// GetOrganizationIdOk returns a tuple with the OrganizationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *LoginFlow) GetOrganizationIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return o.OrganizationId.Get(), o.OrganizationId.IsSet() +} + +// HasOrganizationId returns a boolean if a field has been set. +func (o *LoginFlow) HasOrganizationId() bool { + if o != nil && o.OrganizationId.IsSet() { + return true + } + + return false +} + +// SetOrganizationId gets a reference to the given NullableString and assigns it to the OrganizationId field. +func (o *LoginFlow) SetOrganizationId(v string) { + o.OrganizationId.Set(&v) +} + +// SetOrganizationIdNil sets the value for OrganizationId to be an explicit nil +func (o *LoginFlow) SetOrganizationIdNil() { + o.OrganizationId.Set(nil) +} + +// UnsetOrganizationId ensures that no value is present for OrganizationId, not even an explicit nil +func (o *LoginFlow) UnsetOrganizationId() { + o.OrganizationId.Unset() +} + // GetRefresh returns the Refresh field value if set, zero value otherwise. func (o *LoginFlow) GetRefresh() bool { if o == nil || o.Refresh == nil { @@ -553,6 +597,9 @@ func (o LoginFlow) MarshalJSON() ([]byte, error) { if o.Oauth2LoginRequest != nil { toSerialize["oauth2_login_request"] = o.Oauth2LoginRequest } + if o.OrganizationId.IsSet() { + toSerialize["organization_id"] = o.OrganizationId.Get() + } if o.Refresh != nil { toSerialize["refresh"] = o.Refresh } diff --git a/internal/client-go/model_registration_flow.go b/internal/client-go/model_registration_flow.go index 9b08288d6a16..85d0365ddcb1 100644 --- a/internal/client-go/model_registration_flow.go +++ b/internal/client-go/model_registration_flow.go @@ -28,6 +28,7 @@ type RegistrationFlow struct { // Ory OAuth 2.0 Login Challenge. This value is set using the `login_challenge` query parameter of the registration and login endpoints. If set will cooperate with Ory OAuth2 and OpenID to act as an OAuth2 server / OpenID Provider. Oauth2LoginChallenge *string `json:"oauth2_login_challenge,omitempty"` Oauth2LoginRequest *OAuth2LoginRequest `json:"oauth2_login_request,omitempty"` + OrganizationId NullableString `json:"organization_id,omitempty"` // RequestURL is the initial URL that was requested from Ory Kratos. It can be used to forward information contained in the URL's path or query for example. RequestUrl string `json:"request_url"` // ReturnTo contains the requested return_to URL. @@ -235,6 +236,49 @@ func (o *RegistrationFlow) SetOauth2LoginRequest(v OAuth2LoginRequest) { o.Oauth2LoginRequest = &v } +// GetOrganizationId returns the OrganizationId field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *RegistrationFlow) GetOrganizationId() string { + if o == nil || o.OrganizationId.Get() == nil { + var ret string + return ret + } + return *o.OrganizationId.Get() +} + +// GetOrganizationIdOk returns a tuple with the OrganizationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *RegistrationFlow) GetOrganizationIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return o.OrganizationId.Get(), o.OrganizationId.IsSet() +} + +// HasOrganizationId returns a boolean if a field has been set. +func (o *RegistrationFlow) HasOrganizationId() bool { + if o != nil && o.OrganizationId.IsSet() { + return true + } + + return false +} + +// SetOrganizationId gets a reference to the given NullableString and assigns it to the OrganizationId field. +func (o *RegistrationFlow) SetOrganizationId(v string) { + o.OrganizationId.Set(&v) +} + +// SetOrganizationIdNil sets the value for OrganizationId to be an explicit nil +func (o *RegistrationFlow) SetOrganizationIdNil() { + o.OrganizationId.Set(nil) +} + +// UnsetOrganizationId ensures that no value is present for OrganizationId, not even an explicit nil +func (o *RegistrationFlow) UnsetOrganizationId() { + o.OrganizationId.Unset() +} + // GetRequestUrl returns the RequestUrl field value func (o *RegistrationFlow) GetRequestUrl() string { if o == nil { @@ -449,6 +493,9 @@ func (o RegistrationFlow) MarshalJSON() ([]byte, error) { if o.Oauth2LoginRequest != nil { toSerialize["oauth2_login_request"] = o.Oauth2LoginRequest } + if o.OrganizationId.IsSet() { + toSerialize["organization_id"] = o.OrganizationId.Get() + } if true { toSerialize["request_url"] = o.RequestUrl } diff --git a/internal/client-go/model_session_authentication_method.go b/internal/client-go/model_session_authentication_method.go index 032dfb0cc7f6..c887f7df61c6 100644 --- a/internal/client-go/model_session_authentication_method.go +++ b/internal/client-go/model_session_authentication_method.go @@ -20,8 +20,9 @@ import ( type SessionAuthenticationMethod struct { Aal *AuthenticatorAssuranceLevel `json:"aal,omitempty"` // When the authentication challenge was completed. - CompletedAt *time.Time `json:"completed_at,omitempty"` - Method *string `json:"method,omitempty"` + CompletedAt *time.Time `json:"completed_at,omitempty"` + Method *string `json:"method,omitempty"` + Organization *string `json:"organization,omitempty"` // OIDC or SAML provider id used for authentication Provider *string `json:"provider,omitempty"` } @@ -139,6 +140,38 @@ func (o *SessionAuthenticationMethod) SetMethod(v string) { o.Method = &v } +// GetOrganization returns the Organization field value if set, zero value otherwise. +func (o *SessionAuthenticationMethod) GetOrganization() string { + if o == nil || o.Organization == nil { + var ret string + return ret + } + return *o.Organization +} + +// GetOrganizationOk returns a tuple with the Organization field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SessionAuthenticationMethod) GetOrganizationOk() (*string, bool) { + if o == nil || o.Organization == nil { + return nil, false + } + return o.Organization, true +} + +// HasOrganization returns a boolean if a field has been set. +func (o *SessionAuthenticationMethod) HasOrganization() bool { + if o != nil && o.Organization != nil { + return true + } + + return false +} + +// SetOrganization gets a reference to the given string and assigns it to the Organization field. +func (o *SessionAuthenticationMethod) SetOrganization(v string) { + o.Organization = &v +} + // GetProvider returns the Provider field value if set, zero value otherwise. func (o *SessionAuthenticationMethod) GetProvider() string { if o == nil || o.Provider == nil { @@ -182,6 +215,9 @@ func (o SessionAuthenticationMethod) MarshalJSON() ([]byte, error) { if o.Method != nil { toSerialize["method"] = o.Method } + if o.Organization != nil { + toSerialize["organization"] = o.Organization + } if o.Provider != nil { toSerialize["provider"] = o.Provider } diff --git a/internal/httpclient/api_frontend.go b/internal/httpclient/api_frontend.go index 657a2c6c7721..0260af5a71b6 100644 --- a/internal/httpclient/api_frontend.go +++ b/internal/httpclient/api_frontend.go @@ -941,6 +941,7 @@ type FrontendApiApiCreateBrowserLoginFlowRequest struct { returnTo *string cookie *string loginChallenge *string + organization *string } func (r FrontendApiApiCreateBrowserLoginFlowRequest) Refresh(refresh bool) FrontendApiApiCreateBrowserLoginFlowRequest { @@ -963,6 +964,10 @@ func (r FrontendApiApiCreateBrowserLoginFlowRequest) LoginChallenge(loginChallen r.loginChallenge = &loginChallenge return r } +func (r FrontendApiApiCreateBrowserLoginFlowRequest) Organization(organization string) FrontendApiApiCreateBrowserLoginFlowRequest { + r.organization = &organization + return r +} func (r FrontendApiApiCreateBrowserLoginFlowRequest) Execute() (*LoginFlow, *http.Response, error) { return r.ApiService.CreateBrowserLoginFlowExecute(r) @@ -1041,6 +1046,9 @@ func (a *FrontendApiService) CreateBrowserLoginFlowExecute(r FrontendApiApiCreat if r.loginChallenge != nil { localVarQueryParams.Add("login_challenge", parameterToString(*r.loginChallenge, "")) } + if r.organization != nil { + localVarQueryParams.Add("organization", parameterToString(*r.organization, "")) + } // to determine the Content-Type header localVarHTTPContentTypes := []string{} @@ -1414,6 +1422,7 @@ type FrontendApiApiCreateBrowserRegistrationFlowRequest struct { returnTo *string loginChallenge *string afterVerificationReturnTo *string + organization *string } func (r FrontendApiApiCreateBrowserRegistrationFlowRequest) ReturnTo(returnTo string) FrontendApiApiCreateBrowserRegistrationFlowRequest { @@ -1428,6 +1437,10 @@ func (r FrontendApiApiCreateBrowserRegistrationFlowRequest) AfterVerificationRet r.afterVerificationReturnTo = &afterVerificationReturnTo return r } +func (r FrontendApiApiCreateBrowserRegistrationFlowRequest) Organization(organization string) FrontendApiApiCreateBrowserRegistrationFlowRequest { + r.organization = &organization + return r +} func (r FrontendApiApiCreateBrowserRegistrationFlowRequest) Execute() (*RegistrationFlow, *http.Response, error) { return r.ApiService.CreateBrowserRegistrationFlowExecute(r) @@ -1499,6 +1512,9 @@ func (a *FrontendApiService) CreateBrowserRegistrationFlowExecute(r FrontendApiA if r.afterVerificationReturnTo != nil { localVarQueryParams.Add("after_verification_return_to", parameterToString(*r.afterVerificationReturnTo, "")) } + if r.organization != nil { + localVarQueryParams.Add("organization", parameterToString(*r.organization, "")) + } // to determine the Content-Type header localVarHTTPContentTypes := []string{} diff --git a/internal/httpclient/model_identity.go b/internal/httpclient/model_identity.go index ea9a18b6972b..282821f468ed 100644 --- a/internal/httpclient/model_identity.go +++ b/internal/httpclient/model_identity.go @@ -27,7 +27,8 @@ type Identity struct { // NullJSONRawMessage represents a json.RawMessage that works well with JSON, SQL, and Swagger and is NULLable- MetadataAdmin interface{} `json:"metadata_admin,omitempty"` // NullJSONRawMessage represents a json.RawMessage that works well with JSON, SQL, and Swagger and is NULLable- - MetadataPublic interface{} `json:"metadata_public,omitempty"` + MetadataPublic interface{} `json:"metadata_public,omitempty"` + OrganizationId NullableString `json:"organization_id,omitempty"` // RecoveryAddresses contains all the addresses that can be used to recover an identity. RecoveryAddresses []RecoveryIdentityAddress `json:"recovery_addresses,omitempty"` // SchemaID is the ID of the JSON Schema to be used for validating the identity's traits. @@ -219,6 +220,49 @@ func (o *Identity) SetMetadataPublic(v interface{}) { o.MetadataPublic = v } +// GetOrganizationId returns the OrganizationId field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *Identity) GetOrganizationId() string { + if o == nil || o.OrganizationId.Get() == nil { + var ret string + return ret + } + return *o.OrganizationId.Get() +} + +// GetOrganizationIdOk returns a tuple with the OrganizationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *Identity) GetOrganizationIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return o.OrganizationId.Get(), o.OrganizationId.IsSet() +} + +// HasOrganizationId returns a boolean if a field has been set. +func (o *Identity) HasOrganizationId() bool { + if o != nil && o.OrganizationId.IsSet() { + return true + } + + return false +} + +// SetOrganizationId gets a reference to the given NullableString and assigns it to the OrganizationId field. +func (o *Identity) SetOrganizationId(v string) { + o.OrganizationId.Set(&v) +} + +// SetOrganizationIdNil sets the value for OrganizationId to be an explicit nil +func (o *Identity) SetOrganizationIdNil() { + o.OrganizationId.Set(nil) +} + +// UnsetOrganizationId ensures that no value is present for OrganizationId, not even an explicit nil +func (o *Identity) UnsetOrganizationId() { + o.OrganizationId.Unset() +} + // GetRecoveryAddresses returns the RecoveryAddresses field value if set, zero value otherwise. func (o *Identity) GetRecoveryAddresses() []RecoveryIdentityAddress { if o == nil || o.RecoveryAddresses == nil { @@ -470,6 +514,9 @@ func (o Identity) MarshalJSON() ([]byte, error) { if o.MetadataPublic != nil { toSerialize["metadata_public"] = o.MetadataPublic } + if o.OrganizationId.IsSet() { + toSerialize["organization_id"] = o.OrganizationId.Get() + } if o.RecoveryAddresses != nil { toSerialize["recovery_addresses"] = o.RecoveryAddresses } diff --git a/internal/httpclient/model_identity_credentials_oidc_provider.go b/internal/httpclient/model_identity_credentials_oidc_provider.go index b1ce3cead760..f905f2f60413 100644 --- a/internal/httpclient/model_identity_credentials_oidc_provider.go +++ b/internal/httpclient/model_identity_credentials_oidc_provider.go @@ -20,6 +20,7 @@ type IdentityCredentialsOidcProvider struct { InitialAccessToken *string `json:"initial_access_token,omitempty"` InitialIdToken *string `json:"initial_id_token,omitempty"` InitialRefreshToken *string `json:"initial_refresh_token,omitempty"` + Organization *string `json:"organization,omitempty"` Provider *string `json:"provider,omitempty"` Subject *string `json:"subject,omitempty"` } @@ -137,6 +138,38 @@ func (o *IdentityCredentialsOidcProvider) SetInitialRefreshToken(v string) { o.InitialRefreshToken = &v } +// GetOrganization returns the Organization field value if set, zero value otherwise. +func (o *IdentityCredentialsOidcProvider) GetOrganization() string { + if o == nil || o.Organization == nil { + var ret string + return ret + } + return *o.Organization +} + +// GetOrganizationOk returns a tuple with the Organization field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *IdentityCredentialsOidcProvider) GetOrganizationOk() (*string, bool) { + if o == nil || o.Organization == nil { + return nil, false + } + return o.Organization, true +} + +// HasOrganization returns a boolean if a field has been set. +func (o *IdentityCredentialsOidcProvider) HasOrganization() bool { + if o != nil && o.Organization != nil { + return true + } + + return false +} + +// SetOrganization gets a reference to the given string and assigns it to the Organization field. +func (o *IdentityCredentialsOidcProvider) SetOrganization(v string) { + o.Organization = &v +} + // GetProvider returns the Provider field value if set, zero value otherwise. func (o *IdentityCredentialsOidcProvider) GetProvider() string { if o == nil || o.Provider == nil { @@ -212,6 +245,9 @@ func (o IdentityCredentialsOidcProvider) MarshalJSON() ([]byte, error) { if o.InitialRefreshToken != nil { toSerialize["initial_refresh_token"] = o.InitialRefreshToken } + if o.Organization != nil { + toSerialize["organization"] = o.Organization + } if o.Provider != nil { toSerialize["provider"] = o.Provider } diff --git a/internal/httpclient/model_login_flow.go b/internal/httpclient/model_login_flow.go index dc7c67ea2649..161377f6b680 100644 --- a/internal/httpclient/model_login_flow.go +++ b/internal/httpclient/model_login_flow.go @@ -30,6 +30,7 @@ type LoginFlow struct { // Ory OAuth 2.0 Login Challenge. This value is set using the `login_challenge` query parameter of the registration and login endpoints. If set will cooperate with Ory OAuth2 and OpenID to act as an OAuth2 server / OpenID Provider. Oauth2LoginChallenge *string `json:"oauth2_login_challenge,omitempty"` Oauth2LoginRequest *OAuth2LoginRequest `json:"oauth2_login_request,omitempty"` + OrganizationId NullableString `json:"organization_id,omitempty"` // Refresh stores whether this login flow should enforce re-authentication. Refresh *bool `json:"refresh,omitempty"` // RequestURL is the initial URL that was requested from Ory Kratos. It can be used to forward information contained in the URL's path or query for example. @@ -272,6 +273,49 @@ func (o *LoginFlow) SetOauth2LoginRequest(v OAuth2LoginRequest) { o.Oauth2LoginRequest = &v } +// GetOrganizationId returns the OrganizationId field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *LoginFlow) GetOrganizationId() string { + if o == nil || o.OrganizationId.Get() == nil { + var ret string + return ret + } + return *o.OrganizationId.Get() +} + +// GetOrganizationIdOk returns a tuple with the OrganizationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *LoginFlow) GetOrganizationIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return o.OrganizationId.Get(), o.OrganizationId.IsSet() +} + +// HasOrganizationId returns a boolean if a field has been set. +func (o *LoginFlow) HasOrganizationId() bool { + if o != nil && o.OrganizationId.IsSet() { + return true + } + + return false +} + +// SetOrganizationId gets a reference to the given NullableString and assigns it to the OrganizationId field. +func (o *LoginFlow) SetOrganizationId(v string) { + o.OrganizationId.Set(&v) +} + +// SetOrganizationIdNil sets the value for OrganizationId to be an explicit nil +func (o *LoginFlow) SetOrganizationIdNil() { + o.OrganizationId.Set(nil) +} + +// UnsetOrganizationId ensures that no value is present for OrganizationId, not even an explicit nil +func (o *LoginFlow) UnsetOrganizationId() { + o.OrganizationId.Unset() +} + // GetRefresh returns the Refresh field value if set, zero value otherwise. func (o *LoginFlow) GetRefresh() bool { if o == nil || o.Refresh == nil { @@ -553,6 +597,9 @@ func (o LoginFlow) MarshalJSON() ([]byte, error) { if o.Oauth2LoginRequest != nil { toSerialize["oauth2_login_request"] = o.Oauth2LoginRequest } + if o.OrganizationId.IsSet() { + toSerialize["organization_id"] = o.OrganizationId.Get() + } if o.Refresh != nil { toSerialize["refresh"] = o.Refresh } diff --git a/internal/httpclient/model_registration_flow.go b/internal/httpclient/model_registration_flow.go index 9b08288d6a16..85d0365ddcb1 100644 --- a/internal/httpclient/model_registration_flow.go +++ b/internal/httpclient/model_registration_flow.go @@ -28,6 +28,7 @@ type RegistrationFlow struct { // Ory OAuth 2.0 Login Challenge. This value is set using the `login_challenge` query parameter of the registration and login endpoints. If set will cooperate with Ory OAuth2 and OpenID to act as an OAuth2 server / OpenID Provider. Oauth2LoginChallenge *string `json:"oauth2_login_challenge,omitempty"` Oauth2LoginRequest *OAuth2LoginRequest `json:"oauth2_login_request,omitempty"` + OrganizationId NullableString `json:"organization_id,omitempty"` // RequestURL is the initial URL that was requested from Ory Kratos. It can be used to forward information contained in the URL's path or query for example. RequestUrl string `json:"request_url"` // ReturnTo contains the requested return_to URL. @@ -235,6 +236,49 @@ func (o *RegistrationFlow) SetOauth2LoginRequest(v OAuth2LoginRequest) { o.Oauth2LoginRequest = &v } +// GetOrganizationId returns the OrganizationId field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *RegistrationFlow) GetOrganizationId() string { + if o == nil || o.OrganizationId.Get() == nil { + var ret string + return ret + } + return *o.OrganizationId.Get() +} + +// GetOrganizationIdOk returns a tuple with the OrganizationId field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned +func (o *RegistrationFlow) GetOrganizationIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return o.OrganizationId.Get(), o.OrganizationId.IsSet() +} + +// HasOrganizationId returns a boolean if a field has been set. +func (o *RegistrationFlow) HasOrganizationId() bool { + if o != nil && o.OrganizationId.IsSet() { + return true + } + + return false +} + +// SetOrganizationId gets a reference to the given NullableString and assigns it to the OrganizationId field. +func (o *RegistrationFlow) SetOrganizationId(v string) { + o.OrganizationId.Set(&v) +} + +// SetOrganizationIdNil sets the value for OrganizationId to be an explicit nil +func (o *RegistrationFlow) SetOrganizationIdNil() { + o.OrganizationId.Set(nil) +} + +// UnsetOrganizationId ensures that no value is present for OrganizationId, not even an explicit nil +func (o *RegistrationFlow) UnsetOrganizationId() { + o.OrganizationId.Unset() +} + // GetRequestUrl returns the RequestUrl field value func (o *RegistrationFlow) GetRequestUrl() string { if o == nil { @@ -449,6 +493,9 @@ func (o RegistrationFlow) MarshalJSON() ([]byte, error) { if o.Oauth2LoginRequest != nil { toSerialize["oauth2_login_request"] = o.Oauth2LoginRequest } + if o.OrganizationId.IsSet() { + toSerialize["organization_id"] = o.OrganizationId.Get() + } if true { toSerialize["request_url"] = o.RequestUrl } diff --git a/internal/httpclient/model_session_authentication_method.go b/internal/httpclient/model_session_authentication_method.go index 032dfb0cc7f6..c887f7df61c6 100644 --- a/internal/httpclient/model_session_authentication_method.go +++ b/internal/httpclient/model_session_authentication_method.go @@ -20,8 +20,9 @@ import ( type SessionAuthenticationMethod struct { Aal *AuthenticatorAssuranceLevel `json:"aal,omitempty"` // When the authentication challenge was completed. - CompletedAt *time.Time `json:"completed_at,omitempty"` - Method *string `json:"method,omitempty"` + CompletedAt *time.Time `json:"completed_at,omitempty"` + Method *string `json:"method,omitempty"` + Organization *string `json:"organization,omitempty"` // OIDC or SAML provider id used for authentication Provider *string `json:"provider,omitempty"` } @@ -139,6 +140,38 @@ func (o *SessionAuthenticationMethod) SetMethod(v string) { o.Method = &v } +// GetOrganization returns the Organization field value if set, zero value otherwise. +func (o *SessionAuthenticationMethod) GetOrganization() string { + if o == nil || o.Organization == nil { + var ret string + return ret + } + return *o.Organization +} + +// GetOrganizationOk returns a tuple with the Organization field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SessionAuthenticationMethod) GetOrganizationOk() (*string, bool) { + if o == nil || o.Organization == nil { + return nil, false + } + return o.Organization, true +} + +// HasOrganization returns a boolean if a field has been set. +func (o *SessionAuthenticationMethod) HasOrganization() bool { + if o != nil && o.Organization != nil { + return true + } + + return false +} + +// SetOrganization gets a reference to the given string and assigns it to the Organization field. +func (o *SessionAuthenticationMethod) SetOrganization(v string) { + o.Organization = &v +} + // GetProvider returns the Provider field value if set, zero value otherwise. func (o *SessionAuthenticationMethod) GetProvider() string { if o == nil || o.Provider == nil { @@ -182,6 +215,9 @@ func (o SessionAuthenticationMethod) MarshalJSON() ([]byte, error) { if o.Method != nil { toSerialize["method"] = o.Method } + if o.Organization != nil { + toSerialize["organization"] = o.Organization + } if o.Provider != nil { toSerialize["provider"] = o.Provider } diff --git a/persistence/sql/batch/.snapshots/Test_buildInsertQueryArgs-case=Identities.json b/persistence/sql/batch/.snapshots/Test_buildInsertQueryArgs-case=Identities.json index af21f20a0c1a..1f00a62f1ad6 100644 --- a/persistence/sql/batch/.snapshots/Test_buildInsertQueryArgs-case=Identities.json +++ b/persistence/sql/batch/.snapshots/Test_buildInsertQueryArgs-case=Identities.json @@ -1,6 +1,6 @@ { "TableName": "\"identities\"", - "ColumnsDecl": "\"available_aal\", \"created_at\", \"id\", \"metadata_admin\", \"metadata_public\", \"nid\", \"schema_id\", \"state\", \"state_changed_at\", \"traits\", \"updated_at\"", + "ColumnsDecl": "\"available_aal\", \"created_at\", \"id\", \"metadata_admin\", \"metadata_public\", \"nid\", \"organization_id\", \"schema_id\", \"state\", \"state_changed_at\", \"traits\", \"updated_at\"", "Columns": [ "available_aal", "created_at", @@ -8,11 +8,12 @@ "metadata_admin", "metadata_public", "nid", + "organization_id", "schema_id", "state", "state_changed_at", "traits", "updated_at" ], - "Placeholders": "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + "Placeholders": "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?),\n(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" } diff --git a/persistence/sql/migratest/fixtures/identity/0149ce5f-76a8-4efe-b2e3-431b8c6cceb6.json b/persistence/sql/migratest/fixtures/identity/0149ce5f-76a8-4efe-b2e3-431b8c6cceb6.json index 89f3c2dae2e3..ce936fc2b72c 100644 --- a/persistence/sql/migratest/fixtures/identity/0149ce5f-76a8-4efe-b2e3-431b8c6cceb6.json +++ b/persistence/sql/migratest/fixtures/identity/0149ce5f-76a8-4efe-b2e3-431b8c6cceb6.json @@ -13,5 +13,6 @@ "baz": "bar" }, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null } diff --git a/persistence/sql/migratest/fixtures/identity/0149ce5f-76a8-4efe-b2e3-431b8c6cceb7.json b/persistence/sql/migratest/fixtures/identity/0149ce5f-76a8-4efe-b2e3-431b8c6cceb7.json index 634a2313a48e..2cf762904be8 100644 --- a/persistence/sql/migratest/fixtures/identity/0149ce5f-76a8-4efe-b2e3-431b8c6cceb7.json +++ b/persistence/sql/migratest/fixtures/identity/0149ce5f-76a8-4efe-b2e3-431b8c6cceb7.json @@ -13,5 +13,6 @@ "baz": "bar" }, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null } diff --git a/persistence/sql/migratest/fixtures/identity/196d8c1e-4f04-40f0-94b3-5ec43996b28a.json b/persistence/sql/migratest/fixtures/identity/196d8c1e-4f04-40f0-94b3-5ec43996b28a.json index 86d19547ca63..252268bedab1 100644 --- a/persistence/sql/migratest/fixtures/identity/196d8c1e-4f04-40f0-94b3-5ec43996b28a.json +++ b/persistence/sql/migratest/fixtures/identity/196d8c1e-4f04-40f0-94b3-5ec43996b28a.json @@ -9,5 +9,6 @@ "metadata_public": null, "metadata_admin": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null } diff --git a/persistence/sql/migratest/fixtures/identity/28ff0031-190b-4253-bd15-14308dec013e.json b/persistence/sql/migratest/fixtures/identity/28ff0031-190b-4253-bd15-14308dec013e.json index bed9cbb51ee4..cc42a522a469 100644 --- a/persistence/sql/migratest/fixtures/identity/28ff0031-190b-4253-bd15-14308dec013e.json +++ b/persistence/sql/migratest/fixtures/identity/28ff0031-190b-4253-bd15-14308dec013e.json @@ -13,5 +13,6 @@ "baz": "bar" }, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null } diff --git a/persistence/sql/migratest/fixtures/identity/2ae6a5a7-2983-49e7-a4d8-7740b37c88cb.json b/persistence/sql/migratest/fixtures/identity/2ae6a5a7-2983-49e7-a4d8-7740b37c88cb.json index c4e285232067..9a5802274eb6 100644 --- a/persistence/sql/migratest/fixtures/identity/2ae6a5a7-2983-49e7-a4d8-7740b37c88cb.json +++ b/persistence/sql/migratest/fixtures/identity/2ae6a5a7-2983-49e7-a4d8-7740b37c88cb.json @@ -9,5 +9,6 @@ "metadata_public": null, "metadata_admin": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null } diff --git a/persistence/sql/migratest/fixtures/identity/308929d3-41a2-43fe-a33c-75308539d841.json b/persistence/sql/migratest/fixtures/identity/308929d3-41a2-43fe-a33c-75308539d841.json index fe14d9ad2f99..798d0effced0 100644 --- a/persistence/sql/migratest/fixtures/identity/308929d3-41a2-43fe-a33c-75308539d841.json +++ b/persistence/sql/migratest/fixtures/identity/308929d3-41a2-43fe-a33c-75308539d841.json @@ -13,5 +13,6 @@ "baz": "bar" }, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null } diff --git a/persistence/sql/migratest/fixtures/identity/359963ec-b09b-4ea0-aece-fb4dd95f304a.json b/persistence/sql/migratest/fixtures/identity/359963ec-b09b-4ea0-aece-fb4dd95f304a.json index 93d23ad3c0f8..997e385044f4 100644 --- a/persistence/sql/migratest/fixtures/identity/359963ec-b09b-4ea0-aece-fb4dd95f304a.json +++ b/persistence/sql/migratest/fixtures/identity/359963ec-b09b-4ea0-aece-fb4dd95f304a.json @@ -9,5 +9,6 @@ "metadata_public": null, "metadata_admin": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null } diff --git a/persistence/sql/migratest/fixtures/identity/5ff66179-c240-4703-b0d8-494592cefff5.json b/persistence/sql/migratest/fixtures/identity/5ff66179-c240-4703-b0d8-494592cefff5.json index cf61fd2a8bed..55622d8d10d6 100644 --- a/persistence/sql/migratest/fixtures/identity/5ff66179-c240-4703-b0d8-494592cefff5.json +++ b/persistence/sql/migratest/fixtures/identity/5ff66179-c240-4703-b0d8-494592cefff5.json @@ -45,5 +45,6 @@ "metadata_public": null, "metadata_admin": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null } diff --git a/persistence/sql/migratest/fixtures/identity/a251ebc2-880c-4f76-a8f3-38e6940eab0e.json b/persistence/sql/migratest/fixtures/identity/a251ebc2-880c-4f76-a8f3-38e6940eab0e.json index 9c63190a6fa7..073c8eccc4ba 100644 --- a/persistence/sql/migratest/fixtures/identity/a251ebc2-880c-4f76-a8f3-38e6940eab0e.json +++ b/persistence/sql/migratest/fixtures/identity/a251ebc2-880c-4f76-a8f3-38e6940eab0e.json @@ -62,5 +62,6 @@ "metadata_public": null, "metadata_admin": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null } diff --git a/persistence/sql/migratest/fixtures/identity/d7b9addb-ac15-4bc2-9fa5-562e0bf48755.json b/persistence/sql/migratest/fixtures/identity/d7b9addb-ac15-4bc2-9fa5-562e0bf48755.json index 71f79d95eb9a..2591e1ed43bc 100644 --- a/persistence/sql/migratest/fixtures/identity/d7b9addb-ac15-4bc2-9fa5-562e0bf48755.json +++ b/persistence/sql/migratest/fixtures/identity/d7b9addb-ac15-4bc2-9fa5-562e0bf48755.json @@ -9,5 +9,6 @@ "metadata_public": null, "metadata_admin": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null } diff --git a/persistence/sql/migratest/fixtures/identity/ed253b2c-48ed-4c58-9b6f-1dc963c30a66.json b/persistence/sql/migratest/fixtures/identity/ed253b2c-48ed-4c58-9b6f-1dc963c30a66.json index 6f4d055e1c7a..9a208bfaff8a 100644 --- a/persistence/sql/migratest/fixtures/identity/ed253b2c-48ed-4c58-9b6f-1dc963c30a66.json +++ b/persistence/sql/migratest/fixtures/identity/ed253b2c-48ed-4c58-9b6f-1dc963c30a66.json @@ -9,5 +9,6 @@ "metadata_public": null, "metadata_admin": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null } diff --git a/persistence/sql/migratest/fixtures/login_flow/00b1517f-2467-4aaf-b0a5-82b4a27dcaf5.json b/persistence/sql/migratest/fixtures/login_flow/00b1517f-2467-4aaf-b0a5-82b4a27dcaf5.json index 17f770efbe90..837de1c52731 100644 --- a/persistence/sql/migratest/fixtures/login_flow/00b1517f-2467-4aaf-b0a5-82b4a27dcaf5.json +++ b/persistence/sql/migratest/fixtures/login_flow/00b1517f-2467-4aaf-b0a5-82b4a27dcaf5.json @@ -1,5 +1,6 @@ { "id": "00b1517f-2467-4aaf-b0a5-82b4a27dcaf5", + "organization_id": null, "oauth2_login_challenge": "challenge data", "type": "api", "expires_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/0bc96cc9-dda4-4700-9e42-35731f2af91e.json b/persistence/sql/migratest/fixtures/login_flow/0bc96cc9-dda4-4700-9e42-35731f2af91e.json index ce8841aa07ff..eeaa7f9b8c04 100644 --- a/persistence/sql/migratest/fixtures/login_flow/0bc96cc9-dda4-4700-9e42-35731f2af91e.json +++ b/persistence/sql/migratest/fixtures/login_flow/0bc96cc9-dda4-4700-9e42-35731f2af91e.json @@ -1,5 +1,6 @@ { "id": "0bc96cc9-dda4-4700-9e42-35731f2af91e", + "organization_id": null, "type": "api", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/1fb23c75-b809-42cc-8984-6ca2d0a1192f.json b/persistence/sql/migratest/fixtures/login_flow/1fb23c75-b809-42cc-8984-6ca2d0a1192f.json index 770f0b2e2c38..cd6619eb23c0 100644 --- a/persistence/sql/migratest/fixtures/login_flow/1fb23c75-b809-42cc-8984-6ca2d0a1192f.json +++ b/persistence/sql/migratest/fixtures/login_flow/1fb23c75-b809-42cc-8984-6ca2d0a1192f.json @@ -1,5 +1,6 @@ { "id": "1fb23c75-b809-42cc-8984-6ca2d0a1192f", + "organization_id": null, "type": "api", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/202c1981-1e25-47f0-8764-75ad506c2bec.json b/persistence/sql/migratest/fixtures/login_flow/202c1981-1e25-47f0-8764-75ad506c2bec.json index b6cd377d812f..d5c8bac1fea6 100644 --- a/persistence/sql/migratest/fixtures/login_flow/202c1981-1e25-47f0-8764-75ad506c2bec.json +++ b/persistence/sql/migratest/fixtures/login_flow/202c1981-1e25-47f0-8764-75ad506c2bec.json @@ -1,5 +1,6 @@ { "id": "202c1981-1e25-47f0-8764-75ad506c2bec", + "organization_id": null, "type": "browser", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/349c945a-60f8-436a-a301-7a42c92604f9.json b/persistence/sql/migratest/fixtures/login_flow/349c945a-60f8-436a-a301-7a42c92604f9.json index effdc9f1f2a0..5aca17468521 100644 --- a/persistence/sql/migratest/fixtures/login_flow/349c945a-60f8-436a-a301-7a42c92604f9.json +++ b/persistence/sql/migratest/fixtures/login_flow/349c945a-60f8-436a-a301-7a42c92604f9.json @@ -1,5 +1,6 @@ { "id": "349c945a-60f8-436a-a301-7a42c92604f9", + "organization_id": null, "type": "browser", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/38caf592-b042-4551-b92f-8d5223c2a4e2.json b/persistence/sql/migratest/fixtures/login_flow/38caf592-b042-4551-b92f-8d5223c2a4e2.json index 6eac76a4e91b..83a1fd65700e 100644 --- a/persistence/sql/migratest/fixtures/login_flow/38caf592-b042-4551-b92f-8d5223c2a4e2.json +++ b/persistence/sql/migratest/fixtures/login_flow/38caf592-b042-4551-b92f-8d5223c2a4e2.json @@ -1,5 +1,6 @@ { "id": "38caf592-b042-4551-b92f-8d5223c2a4e2", + "organization_id": null, "type": "api", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/3a9ea34f-0f12-469b-9417-3ae5795a7baa.json b/persistence/sql/migratest/fixtures/login_flow/3a9ea34f-0f12-469b-9417-3ae5795a7baa.json index 577b054917db..7a56b04c704b 100644 --- a/persistence/sql/migratest/fixtures/login_flow/3a9ea34f-0f12-469b-9417-3ae5795a7baa.json +++ b/persistence/sql/migratest/fixtures/login_flow/3a9ea34f-0f12-469b-9417-3ae5795a7baa.json @@ -1,5 +1,6 @@ { "id": "3a9ea34f-0f12-469b-9417-3ae5795a7baa", + "organization_id": null, "type": "browser", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/43c99182-bb67-47e1-b564-bb23bd8d4393.json b/persistence/sql/migratest/fixtures/login_flow/43c99182-bb67-47e1-b564-bb23bd8d4393.json index 6f0fae29f575..392e31ac4aeb 100644 --- a/persistence/sql/migratest/fixtures/login_flow/43c99182-bb67-47e1-b564-bb23bd8d4393.json +++ b/persistence/sql/migratest/fixtures/login_flow/43c99182-bb67-47e1-b564-bb23bd8d4393.json @@ -1,5 +1,6 @@ { "id": "43c99182-bb67-47e1-b564-bb23bd8d4393", + "organization_id": null, "type": "browser", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/47edd3a8-0998-4779-9469-f4b8ee4430df.json b/persistence/sql/migratest/fixtures/login_flow/47edd3a8-0998-4779-9469-f4b8ee4430df.json index 64a415dfba4a..d9244b34ed63 100644 --- a/persistence/sql/migratest/fixtures/login_flow/47edd3a8-0998-4779-9469-f4b8ee4430df.json +++ b/persistence/sql/migratest/fixtures/login_flow/47edd3a8-0998-4779-9469-f4b8ee4430df.json @@ -1,5 +1,6 @@ { "id": "47edd3a8-0998-4779-9469-f4b8ee4430df", + "organization_id": null, "type": "api", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/56d94e8b-8a5d-4b7f-8a6e-3259d2b2903e.json b/persistence/sql/migratest/fixtures/login_flow/56d94e8b-8a5d-4b7f-8a6e-3259d2b2903e.json index e2ccb8f7616d..8307d8ff37c5 100644 --- a/persistence/sql/migratest/fixtures/login_flow/56d94e8b-8a5d-4b7f-8a6e-3259d2b2903e.json +++ b/persistence/sql/migratest/fixtures/login_flow/56d94e8b-8a5d-4b7f-8a6e-3259d2b2903e.json @@ -1,5 +1,6 @@ { "id": "56d94e8b-8a5d-4b7f-8a6e-3259d2b2903e", + "organization_id": null, "type": "browser", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/6d387820-f2f4-4f9f-9980-a90d89e7811f.json b/persistence/sql/migratest/fixtures/login_flow/6d387820-f2f4-4f9f-9980-a90d89e7811f.json index 863594687d00..114fc6b8e0b2 100644 --- a/persistence/sql/migratest/fixtures/login_flow/6d387820-f2f4-4f9f-9980-a90d89e7811f.json +++ b/persistence/sql/migratest/fixtures/login_flow/6d387820-f2f4-4f9f-9980-a90d89e7811f.json @@ -1,5 +1,6 @@ { "id": "6d387820-f2f4-4f9f-9980-a90d89e7811f", + "organization_id": null, "type": "browser", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/916ded11-aa64-4a27-b06e-96e221a509d7.json b/persistence/sql/migratest/fixtures/login_flow/916ded11-aa64-4a27-b06e-96e221a509d7.json index 138f4838c466..27c654033fa6 100644 --- a/persistence/sql/migratest/fixtures/login_flow/916ded11-aa64-4a27-b06e-96e221a509d7.json +++ b/persistence/sql/migratest/fixtures/login_flow/916ded11-aa64-4a27-b06e-96e221a509d7.json @@ -1,5 +1,6 @@ { "id": "916ded11-aa64-4a27-b06e-96e221a509d7", + "organization_id": null, "type": "browser", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/99974ce6-388c-4669-a95a-7757ee724020.json b/persistence/sql/migratest/fixtures/login_flow/99974ce6-388c-4669-a95a-7757ee724020.json index 41bc0e84748f..bfcc30b0f79b 100644 --- a/persistence/sql/migratest/fixtures/login_flow/99974ce6-388c-4669-a95a-7757ee724020.json +++ b/persistence/sql/migratest/fixtures/login_flow/99974ce6-388c-4669-a95a-7757ee724020.json @@ -1,5 +1,6 @@ { "id": "99974ce6-388c-4669-a95a-7757ee724020", + "organization_id": null, "type": "browser", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/b1fac7fb-d016-4a06-a7fe-e4eab2a0429f.json b/persistence/sql/migratest/fixtures/login_flow/b1fac7fb-d016-4a06-a7fe-e4eab2a0429f.json index ae28f38c8fe4..0023c80a2a3b 100644 --- a/persistence/sql/migratest/fixtures/login_flow/b1fac7fb-d016-4a06-a7fe-e4eab2a0429f.json +++ b/persistence/sql/migratest/fixtures/login_flow/b1fac7fb-d016-4a06-a7fe-e4eab2a0429f.json @@ -1,5 +1,6 @@ { "id": "b1fac7fb-d016-4a06-a7fe-e4eab2a0429f", + "organization_id": null, "type": "api", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/cccccccc-dda4-4700-9e42-35731f2af911.json b/persistence/sql/migratest/fixtures/login_flow/cccccccc-dda4-4700-9e42-35731f2af911.json index a2b9861acec7..e48d123f8904 100644 --- a/persistence/sql/migratest/fixtures/login_flow/cccccccc-dda4-4700-9e42-35731f2af911.json +++ b/persistence/sql/migratest/fixtures/login_flow/cccccccc-dda4-4700-9e42-35731f2af911.json @@ -1,5 +1,6 @@ { "id": "cccccccc-dda4-4700-9e42-35731f2af911", + "organization_id": null, "oauth2_login_challenge": "challenge data", "type": "api", "expires_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/cccccccc-dda4-4700-9e42-35731f2af91e.json b/persistence/sql/migratest/fixtures/login_flow/cccccccc-dda4-4700-9e42-35731f2af91e.json index e2d58f6dc1fe..ca25b3085c8b 100644 --- a/persistence/sql/migratest/fixtures/login_flow/cccccccc-dda4-4700-9e42-35731f2af91e.json +++ b/persistence/sql/migratest/fixtures/login_flow/cccccccc-dda4-4700-9e42-35731f2af91e.json @@ -1,5 +1,6 @@ { "id": "cccccccc-dda4-4700-9e42-35731f2af91e", + "organization_id": null, "oauth2_login_challenge": "challenge data", "type": "api", "expires_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/login_flow/d6aa1f23-88c9-4b9b-a850-392f48c7f9e8.json b/persistence/sql/migratest/fixtures/login_flow/d6aa1f23-88c9-4b9b-a850-392f48c7f9e8.json index 00a1a2d7c3e5..6b60fce7bc97 100644 --- a/persistence/sql/migratest/fixtures/login_flow/d6aa1f23-88c9-4b9b-a850-392f48c7f9e8.json +++ b/persistence/sql/migratest/fixtures/login_flow/d6aa1f23-88c9-4b9b-a850-392f48c7f9e8.json @@ -1,5 +1,6 @@ { "id": "d6aa1f23-88c9-4b9b-a850-392f48c7f9e8", + "organization_id": null, "type": "api", "expires_at": "2013-10-07T08:23:19Z", "issued_at": "2013-10-07T08:23:19Z", diff --git a/persistence/sql/migratest/fixtures/registration_flow/05a7f09d-4ef3-41fb-958a-6ad74584b36a.json b/persistence/sql/migratest/fixtures/registration_flow/05a7f09d-4ef3-41fb-958a-6ad74584b36a.json index ccfcf94814a5..beb3815ee0d2 100644 --- a/persistence/sql/migratest/fixtures/registration_flow/05a7f09d-4ef3-41fb-958a-6ad74584b36a.json +++ b/persistence/sql/migratest/fixtures/registration_flow/05a7f09d-4ef3-41fb-958a-6ad74584b36a.json @@ -9,5 +9,6 @@ "method": "", "nodes": null }, + "organization_id": null, "state": "" } diff --git a/persistence/sql/migratest/fixtures/registration_flow/22d58184-b97d-44a5-bbaf-0aa8b4000d81.json b/persistence/sql/migratest/fixtures/registration_flow/22d58184-b97d-44a5-bbaf-0aa8b4000d81.json index 5c110a3394f5..22559499461d 100644 --- a/persistence/sql/migratest/fixtures/registration_flow/22d58184-b97d-44a5-bbaf-0aa8b4000d81.json +++ b/persistence/sql/migratest/fixtures/registration_flow/22d58184-b97d-44a5-bbaf-0aa8b4000d81.json @@ -9,5 +9,6 @@ "method": "", "nodes": null }, + "organization_id": null, "state": "" } diff --git a/persistence/sql/migratest/fixtures/registration_flow/2bf132e0-5d40-4df9-9a11-9106e5333735.json b/persistence/sql/migratest/fixtures/registration_flow/2bf132e0-5d40-4df9-9a11-9106e5333735.json index 8df52efff06b..bb9d425d6001 100644 --- a/persistence/sql/migratest/fixtures/registration_flow/2bf132e0-5d40-4df9-9a11-9106e5333735.json +++ b/persistence/sql/migratest/fixtures/registration_flow/2bf132e0-5d40-4df9-9a11-9106e5333735.json @@ -9,5 +9,6 @@ "method": "", "nodes": null }, + "organization_id": null, "state": "" } diff --git a/persistence/sql/migratest/fixtures/registration_flow/696e7022-c466-44f6-89c6-8cf93c06a62a.json b/persistence/sql/migratest/fixtures/registration_flow/696e7022-c466-44f6-89c6-8cf93c06a62a.json index d58beb9edffc..a7ccfd6f84b7 100644 --- a/persistence/sql/migratest/fixtures/registration_flow/696e7022-c466-44f6-89c6-8cf93c06a62a.json +++ b/persistence/sql/migratest/fixtures/registration_flow/696e7022-c466-44f6-89c6-8cf93c06a62a.json @@ -10,5 +10,6 @@ "method": "", "nodes": null }, + "organization_id": null, "state": "" } diff --git a/persistence/sql/migratest/fixtures/registration_flow/69c80296-36cd-4afc-921a-15369cac5bf0.json b/persistence/sql/migratest/fixtures/registration_flow/69c80296-36cd-4afc-921a-15369cac5bf0.json index 6179619c71fe..10c88c29c5a9 100644 --- a/persistence/sql/migratest/fixtures/registration_flow/69c80296-36cd-4afc-921a-15369cac5bf0.json +++ b/persistence/sql/migratest/fixtures/registration_flow/69c80296-36cd-4afc-921a-15369cac5bf0.json @@ -10,5 +10,6 @@ "method": "", "nodes": null }, + "organization_id": null, "state": "choose_method" } diff --git a/persistence/sql/migratest/fixtures/registration_flow/87fa3f43-5155-42b4-a1ad-174c2595fdaf.json b/persistence/sql/migratest/fixtures/registration_flow/87fa3f43-5155-42b4-a1ad-174c2595fdaf.json index 19104b6d9f26..95d84caf5235 100644 --- a/persistence/sql/migratest/fixtures/registration_flow/87fa3f43-5155-42b4-a1ad-174c2595fdaf.json +++ b/persistence/sql/migratest/fixtures/registration_flow/87fa3f43-5155-42b4-a1ad-174c2595fdaf.json @@ -10,5 +10,6 @@ "method": "", "nodes": null }, + "organization_id": null, "state": "" } diff --git a/persistence/sql/migratest/fixtures/registration_flow/8ef215a9-e8d5-43b3-9aa3-cb4333562e36.json b/persistence/sql/migratest/fixtures/registration_flow/8ef215a9-e8d5-43b3-9aa3-cb4333562e36.json index 616af278cd82..68f36b946d79 100644 --- a/persistence/sql/migratest/fixtures/registration_flow/8ef215a9-e8d5-43b3-9aa3-cb4333562e36.json +++ b/persistence/sql/migratest/fixtures/registration_flow/8ef215a9-e8d5-43b3-9aa3-cb4333562e36.json @@ -10,5 +10,6 @@ "method": "", "nodes": null }, + "organization_id": null, "state": "" } diff --git a/persistence/sql/migratest/fixtures/registration_flow/8f32efdc-f6fc-4c27-a3c2-579d109eff60.json b/persistence/sql/migratest/fixtures/registration_flow/8f32efdc-f6fc-4c27-a3c2-579d109eff60.json index a1f323ba3c4d..4226d48042ef 100644 --- a/persistence/sql/migratest/fixtures/registration_flow/8f32efdc-f6fc-4c27-a3c2-579d109eff60.json +++ b/persistence/sql/migratest/fixtures/registration_flow/8f32efdc-f6fc-4c27-a3c2-579d109eff60.json @@ -10,5 +10,6 @@ "method": "", "nodes": null }, + "organization_id": null, "state": "" } diff --git a/persistence/sql/migratest/fixtures/registration_flow/9edcf051-1cd0-44cc-bd2f-6ac21f0c24dd.json b/persistence/sql/migratest/fixtures/registration_flow/9edcf051-1cd0-44cc-bd2f-6ac21f0c24dd.json index 1e6cc2579af2..2501f4fcef9c 100644 --- a/persistence/sql/migratest/fixtures/registration_flow/9edcf051-1cd0-44cc-bd2f-6ac21f0c24dd.json +++ b/persistence/sql/migratest/fixtures/registration_flow/9edcf051-1cd0-44cc-bd2f-6ac21f0c24dd.json @@ -10,5 +10,6 @@ "method": "", "nodes": null }, + "organization_id": null, "state": "" } diff --git a/persistence/sql/migratest/fixtures/registration_flow/e2150cdc-23ac-4940-a240-6c79c27ab029.json b/persistence/sql/migratest/fixtures/registration_flow/e2150cdc-23ac-4940-a240-6c79c27ab029.json index 560741f9a18d..15173755e9e4 100644 --- a/persistence/sql/migratest/fixtures/registration_flow/e2150cdc-23ac-4940-a240-6c79c27ab029.json +++ b/persistence/sql/migratest/fixtures/registration_flow/e2150cdc-23ac-4940-a240-6c79c27ab029.json @@ -10,5 +10,6 @@ "method": "", "nodes": null }, + "organization_id": null, "state": "" } diff --git a/persistence/sql/migratest/fixtures/registration_flow/ef18b06e-4700-4021-9949-ef783cd86be1.json b/persistence/sql/migratest/fixtures/registration_flow/ef18b06e-4700-4021-9949-ef783cd86be1.json index ce1272433edf..da36c662bfe5 100644 --- a/persistence/sql/migratest/fixtures/registration_flow/ef18b06e-4700-4021-9949-ef783cd86be1.json +++ b/persistence/sql/migratest/fixtures/registration_flow/ef18b06e-4700-4021-9949-ef783cd86be1.json @@ -10,5 +10,6 @@ "method": "", "nodes": null }, + "organization_id": null, "state": "" } diff --git a/persistence/sql/migratest/fixtures/registration_flow/ef18b06e-4700-4021-9949-ef783cd86be8.json b/persistence/sql/migratest/fixtures/registration_flow/ef18b06e-4700-4021-9949-ef783cd86be8.json index 4d1d58bdaf51..68bfeb3da8b0 100644 --- a/persistence/sql/migratest/fixtures/registration_flow/ef18b06e-4700-4021-9949-ef783cd86be8.json +++ b/persistence/sql/migratest/fixtures/registration_flow/ef18b06e-4700-4021-9949-ef783cd86be8.json @@ -10,5 +10,6 @@ "method": "", "nodes": null }, + "organization_id": null, "state": "" } diff --git a/persistence/sql/migratest/fixtures/registration_flow/f1b5ed18-113a-4a98-aae7-d4eba007199c.json b/persistence/sql/migratest/fixtures/registration_flow/f1b5ed18-113a-4a98-aae7-d4eba007199c.json index c7d1b8207a4e..4c10f10594e4 100644 --- a/persistence/sql/migratest/fixtures/registration_flow/f1b5ed18-113a-4a98-aae7-d4eba007199c.json +++ b/persistence/sql/migratest/fixtures/registration_flow/f1b5ed18-113a-4a98-aae7-d4eba007199c.json @@ -10,5 +10,6 @@ "method": "", "nodes": null }, + "organization_id": null, "state": "" } diff --git a/persistence/sql/migratest/fixtures/session/068f6bb6-d15f-436d-94f7-b3fd0489c9ef.json b/persistence/sql/migratest/fixtures/session/068f6bb6-d15f-436d-94f7-b3fd0489c9ef.json index 8c641a193e30..4c8fb26fc316 100644 --- a/persistence/sql/migratest/fixtures/session/068f6bb6-d15f-436d-94f7-b3fd0489c9ef.json +++ b/persistence/sql/migratest/fixtures/session/068f6bb6-d15f-436d-94f7-b3fd0489c9ef.json @@ -38,7 +38,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "devices": [] } diff --git a/persistence/sql/migratest/fixtures/session/7458af86-c1d8-401c-978a-8da89133f78b.json b/persistence/sql/migratest/fixtures/session/7458af86-c1d8-401c-978a-8da89133f78b.json index 990e5925ec0e..8d96bfed4e84 100644 --- a/persistence/sql/migratest/fixtures/session/7458af86-c1d8-401c-978a-8da89133f78b.json +++ b/persistence/sql/migratest/fixtures/session/7458af86-c1d8-401c-978a-8da89133f78b.json @@ -38,7 +38,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "devices": [] } diff --git a/persistence/sql/migratest/fixtures/session/7458af86-c1d8-401c-978a-8da89133f98b.json b/persistence/sql/migratest/fixtures/session/7458af86-c1d8-401c-978a-8da89133f98b.json index ccc7ed2e0a63..c033cccee191 100644 --- a/persistence/sql/migratest/fixtures/session/7458af86-c1d8-401c-978a-8da89133f98b.json +++ b/persistence/sql/migratest/fixtures/session/7458af86-c1d8-401c-978a-8da89133f98b.json @@ -38,7 +38,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "devices": [ { diff --git a/persistence/sql/migratest/fixtures/session/8571e374-38f2-4f46-8ad3-b9d914e174d3.json b/persistence/sql/migratest/fixtures/session/8571e374-38f2-4f46-8ad3-b9d914e174d3.json index 24e7ac8f3535..625530c7007b 100644 --- a/persistence/sql/migratest/fixtures/session/8571e374-38f2-4f46-8ad3-b9d914e174d3.json +++ b/persistence/sql/migratest/fixtures/session/8571e374-38f2-4f46-8ad3-b9d914e174d3.json @@ -33,7 +33,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "devices": [] } diff --git a/persistence/sql/migratest/fixtures/session/dcde5aaa-f789-4d3d-ae1f-76da8d57e67c.json b/persistence/sql/migratest/fixtures/session/dcde5aaa-f789-4d3d-ae1f-76da8d57e67c.json index dcec9dc414a3..895bfdffbeda 100644 --- a/persistence/sql/migratest/fixtures/session/dcde5aaa-f789-4d3d-ae1f-76da8d57e67c.json +++ b/persistence/sql/migratest/fixtures/session/dcde5aaa-f789-4d3d-ae1f-76da8d57e67c.json @@ -33,7 +33,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "devices": [] } diff --git a/persistence/sql/migratest/fixtures/session/f38cdebe-e567-42c9-a562-1bd4dee40998.json b/persistence/sql/migratest/fixtures/session/f38cdebe-e567-42c9-a562-1bd4dee40998.json index 6fcad6937cc0..1b4474dc4269 100644 --- a/persistence/sql/migratest/fixtures/session/f38cdebe-e567-42c9-a562-1bd4dee40998.json +++ b/persistence/sql/migratest/fixtures/session/f38cdebe-e567-42c9-a562-1bd4dee40998.json @@ -33,7 +33,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "devices": [] } diff --git a/persistence/sql/migratest/fixtures/settings_flow/194c5b05-0487-4a11-bcbc-f301c9ff9678.json b/persistence/sql/migratest/fixtures/settings_flow/194c5b05-0487-4a11-bcbc-f301c9ff9678.json index 7733d6357033..258dcd97e8b4 100644 --- a/persistence/sql/migratest/fixtures/settings_flow/194c5b05-0487-4a11-bcbc-f301c9ff9678.json +++ b/persistence/sql/migratest/fixtures/settings_flow/194c5b05-0487-4a11-bcbc-f301c9ff9678.json @@ -57,7 +57,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "state": "show_form" } diff --git a/persistence/sql/migratest/fixtures/settings_flow/19ede218-928c-4e02-ab49-b76e12b34f31.json b/persistence/sql/migratest/fixtures/settings_flow/19ede218-928c-4e02-ab49-b76e12b34f31.json index 3b7d3348a868..d14aec4ca29f 100644 --- a/persistence/sql/migratest/fixtures/settings_flow/19ede218-928c-4e02-ab49-b76e12b34f31.json +++ b/persistence/sql/migratest/fixtures/settings_flow/19ede218-928c-4e02-ab49-b76e12b34f31.json @@ -58,7 +58,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "state": "show_form" } diff --git a/persistence/sql/migratest/fixtures/settings_flow/19ede218-928c-4e02-ab49-b76e12b34f32.json b/persistence/sql/migratest/fixtures/settings_flow/19ede218-928c-4e02-ab49-b76e12b34f32.json index 4c42c9c07cd4..04e2d50e6d95 100644 --- a/persistence/sql/migratest/fixtures/settings_flow/19ede218-928c-4e02-ab49-b76e12b34f32.json +++ b/persistence/sql/migratest/fixtures/settings_flow/19ede218-928c-4e02-ab49-b76e12b34f32.json @@ -58,7 +58,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "state": "show_form" } diff --git a/persistence/sql/migratest/fixtures/settings_flow/21c5f714-3089-49d2-b387-f244d4dd9e00.json b/persistence/sql/migratest/fixtures/settings_flow/21c5f714-3089-49d2-b387-f244d4dd9e00.json index a66391f475fa..691eeee92d02 100644 --- a/persistence/sql/migratest/fixtures/settings_flow/21c5f714-3089-49d2-b387-f244d4dd9e00.json +++ b/persistence/sql/migratest/fixtures/settings_flow/21c5f714-3089-49d2-b387-f244d4dd9e00.json @@ -58,7 +58,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "state": "show_form" } diff --git a/persistence/sql/migratest/fixtures/settings_flow/74fd6c53-7651-453e-90b8-2c5adbf911bb.json b/persistence/sql/migratest/fixtures/settings_flow/74fd6c53-7651-453e-90b8-2c5adbf911bb.json index a1499fa10e1c..33055e289329 100644 --- a/persistence/sql/migratest/fixtures/settings_flow/74fd6c53-7651-453e-90b8-2c5adbf911bb.json +++ b/persistence/sql/migratest/fixtures/settings_flow/74fd6c53-7651-453e-90b8-2c5adbf911bb.json @@ -30,7 +30,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "state": "show_form" } diff --git a/persistence/sql/migratest/fixtures/settings_flow/77fe4fb3-2d4e-4532-b568-c44b0aece0aa.json b/persistence/sql/migratest/fixtures/settings_flow/77fe4fb3-2d4e-4532-b568-c44b0aece0aa.json index 0d7893fdd23c..e4b41a57eda1 100644 --- a/persistence/sql/migratest/fixtures/settings_flow/77fe4fb3-2d4e-4532-b568-c44b0aece0aa.json +++ b/persistence/sql/migratest/fixtures/settings_flow/77fe4fb3-2d4e-4532-b568-c44b0aece0aa.json @@ -58,7 +58,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "state": "show_form" } diff --git a/persistence/sql/migratest/fixtures/settings_flow/8248bb5d-8ef7-45e3-8e07-9e2003dd5352.json b/persistence/sql/migratest/fixtures/settings_flow/8248bb5d-8ef7-45e3-8e07-9e2003dd5352.json index 2f3a9a21496c..87af942e7177 100644 --- a/persistence/sql/migratest/fixtures/settings_flow/8248bb5d-8ef7-45e3-8e07-9e2003dd5352.json +++ b/persistence/sql/migratest/fixtures/settings_flow/8248bb5d-8ef7-45e3-8e07-9e2003dd5352.json @@ -58,7 +58,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "state": "show_form" } diff --git a/persistence/sql/migratest/fixtures/settings_flow/90b4f970-b9ae-42bc-a0a7-73ec750e0aa1.json b/persistence/sql/migratest/fixtures/settings_flow/90b4f970-b9ae-42bc-a0a7-73ec750e0aa1.json index b13dadb6aba2..3df5e29f2a61 100644 --- a/persistence/sql/migratest/fixtures/settings_flow/90b4f970-b9ae-42bc-a0a7-73ec750e0aa1.json +++ b/persistence/sql/migratest/fixtures/settings_flow/90b4f970-b9ae-42bc-a0a7-73ec750e0aa1.json @@ -58,7 +58,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "state": "show_form" } diff --git a/persistence/sql/migratest/fixtures/settings_flow/a79bfcf1-68ae-49de-8b23-4f96921b8341.json b/persistence/sql/migratest/fixtures/settings_flow/a79bfcf1-68ae-49de-8b23-4f96921b8341.json index cc80b32fb4ae..03890e50ef6b 100644 --- a/persistence/sql/migratest/fixtures/settings_flow/a79bfcf1-68ae-49de-8b23-4f96921b8341.json +++ b/persistence/sql/migratest/fixtures/settings_flow/a79bfcf1-68ae-49de-8b23-4f96921b8341.json @@ -58,7 +58,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "state": "show_form" } diff --git a/persistence/sql/migratest/fixtures/settings_flow/aeba85bd-1a8c-44bf-8fc3-3be83c01a3dc.json b/persistence/sql/migratest/fixtures/settings_flow/aeba85bd-1a8c-44bf-8fc3-3be83c01a3dc.json index d2409100456c..67a14d02dadb 100644 --- a/persistence/sql/migratest/fixtures/settings_flow/aeba85bd-1a8c-44bf-8fc3-3be83c01a3dc.json +++ b/persistence/sql/migratest/fixtures/settings_flow/aeba85bd-1a8c-44bf-8fc3-3be83c01a3dc.json @@ -58,7 +58,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "state": "show_form" } diff --git a/persistence/sql/migratest/fixtures/settings_flow/cdfd1eed-34a4-491d-ad0a-7579d3a0a7ba.json b/persistence/sql/migratest/fixtures/settings_flow/cdfd1eed-34a4-491d-ad0a-7579d3a0a7ba.json index 4fdbab4b561e..c4850694d35f 100644 --- a/persistence/sql/migratest/fixtures/settings_flow/cdfd1eed-34a4-491d-ad0a-7579d3a0a7ba.json +++ b/persistence/sql/migratest/fixtures/settings_flow/cdfd1eed-34a4-491d-ad0a-7579d3a0a7ba.json @@ -58,7 +58,8 @@ ], "metadata_public": null, "created_at": "2013-10-07T08:23:19Z", - "updated_at": "2013-10-07T08:23:19Z" + "updated_at": "2013-10-07T08:23:19Z", + "organization_id": null }, "state": "show_form" } diff --git a/persistence/sql/migrations/sql/20230907085000000000_add_organization_id.down.sql b/persistence/sql/migrations/sql/20230907085000000000_add_organization_id.down.sql new file mode 100644 index 000000000000..d9e10922355b --- /dev/null +++ b/persistence/sql/migrations/sql/20230907085000000000_add_organization_id.down.sql @@ -0,0 +1,3 @@ +alter table selfservice_login_flows drop column organization_id; +alter table selfservice_registration_flows drop column organization_id; +alter table identities drop column organization_id; diff --git a/persistence/sql/migrations/sql/20230907085000000000_add_organization_id.mysql.up.sql b/persistence/sql/migrations/sql/20230907085000000000_add_organization_id.mysql.up.sql new file mode 100644 index 000000000000..55974d67d24b --- /dev/null +++ b/persistence/sql/migrations/sql/20230907085000000000_add_organization_id.mysql.up.sql @@ -0,0 +1,3 @@ +alter table selfservice_login_flows add column organization_id char(36) null; +alter table selfservice_registration_flows add column organization_id char(36) null; +alter table identities add column organization_id char(36) null; diff --git a/persistence/sql/migrations/sql/20230907085000000000_add_organization_id.up.sql b/persistence/sql/migrations/sql/20230907085000000000_add_organization_id.up.sql new file mode 100644 index 000000000000..8f2be2cbadb2 --- /dev/null +++ b/persistence/sql/migrations/sql/20230907085000000000_add_organization_id.up.sql @@ -0,0 +1,3 @@ +alter table selfservice_login_flows add column organization_id uuid null; +alter table selfservice_registration_flows add column organization_id uuid null; +alter table identities add column organization_id uuid null; diff --git a/selfservice/flow/login/flow.go b/selfservice/flow/login/flow.go index 6e7426bd578c..1bd95c7b1fad 100644 --- a/selfservice/flow/login/flow.go +++ b/selfservice/flow/login/flow.go @@ -50,8 +50,9 @@ type Flow struct { // represents the id in the login UI's query parameter: http:///?flow= // // required: true - ID uuid.UUID `json:"id" faker:"-" db:"id" rw:"r"` - NID uuid.UUID `json:"-" faker:"-" db:"nid"` + ID uuid.UUID `json:"id" faker:"-" db:"id" rw:"r"` + NID uuid.UUID `json:"-" faker:"-" db:"nid"` + OrganizationID uuid.NullUUID `json:"organization_id,omitempty" faker:"-" db:"organization_id"` // Ory OAuth 2.0 Login Challenge. // diff --git a/selfservice/flow/login/handler.go b/selfservice/flow/login/handler.go index aa512f8c2574..e965d9758025 100644 --- a/selfservice/flow/login/handler.go +++ b/selfservice/flow/login/handler.go @@ -56,6 +56,7 @@ type ( config.Provider ErrorHandlerProvider sessiontokenexchange.PersistenceProvider + x.LoggingProvider } HandlerProvider interface { LoginHandler() *Handler @@ -187,8 +188,17 @@ preLoginHook: f.UI.Messages.Add(text.NewInfoLoginMFA()) } - var s Strategy - for _, s = range h.d.LoginStrategies(r.Context()) { + var strategyFilters []StrategyFilter + if rawOrg := r.URL.Query().Get("organization"); rawOrg != "" { + orgID, err := uuid.FromString(rawOrg) + if err != nil { + h.d.Logger().WithError(err).Warnf("Ignoring invalid UUID %q in query parameter `organization`.", rawOrg) + } else { + f.OrganizationID = uuid.NullUUID{UUID: orgID, Valid: true} + strategyFilters = []StrategyFilter{func(s Strategy) bool { return s.ID() == identity.CredentialsTypeOIDC }} + } + } + for _, s := range h.d.LoginStrategies(r.Context(), strategyFilters...) { if err := s.PopulateLoginMethod(r, f.RequestedAAL, f); err != nil { return nil, nil, err } @@ -360,6 +370,13 @@ type createBrowserLoginFlow struct { // required: false // in: query HydraLoginChallenge string `json:"login_challenge"` + + // An optional organization ID that should be used for logging this user in. + // This parameter is only effective in the Ory Network. + // + // required: false + // in: query + Organization string `json:"organization"` } // swagger:route GET /self-service/login/browser frontend createBrowserLoginFlow diff --git a/selfservice/flow/login/strategy.go b/selfservice/flow/login/strategy.go index 91de3d276963..818ecfea9cf0 100644 --- a/selfservice/flow/login/strategy.go +++ b/selfservice/flow/login/strategy.go @@ -55,7 +55,9 @@ func (s Strategies) RegisterPublicRoutes(r *x.RouterPublic) { } } +type StrategyFilter func(strategy Strategy) bool + type StrategyProvider interface { AllLoginStrategies() Strategies - LoginStrategies(ctx context.Context) Strategies + LoginStrategies(ctx context.Context, filters ...StrategyFilter) Strategies } diff --git a/selfservice/flow/registration/flow.go b/selfservice/flow/registration/flow.go index 085cf353c8be..494bf72383af 100644 --- a/selfservice/flow/registration/flow.go +++ b/selfservice/flow/registration/flow.go @@ -99,8 +99,9 @@ type Flow struct { UpdatedAt time.Time `json:"-" faker:"-" db:"updated_at"` // CSRFToken contains the anti-csrf token associated with this flow. Only set for browser flows. - CSRFToken string `json:"-" db:"csrf_token"` - NID uuid.UUID `json:"-" faker:"-" db:"nid"` + CSRFToken string `json:"-" db:"csrf_token"` + NID uuid.UUID `json:"-" faker:"-" db:"nid"` + OrganizationID uuid.NullUUID `json:"organization_id,omitempty" faker:"-" db:"organization_id"` // TransientPayload is used to pass data from the registration to a webhook TransientPayload json.RawMessage `json:"transient_payload,omitempty" faker:"-" db:"-"` diff --git a/selfservice/flow/registration/handler.go b/selfservice/flow/registration/handler.go index 91242f6bf26b..d58ff4c9e735 100644 --- a/selfservice/flow/registration/handler.go +++ b/selfservice/flow/registration/handler.go @@ -8,6 +8,8 @@ import ( "net/url" "time" + "github.com/gofrs/uuid" + "github.com/ory/herodot" "github.com/ory/kratos/hydra" "github.com/ory/kratos/selfservice/sessiontokenexchange" @@ -57,6 +59,7 @@ type ( FlowPersistenceProvider ErrorHandlerProvider sessiontokenexchange.PersistenceProvider + x.LoggingProvider } HandlerProvider interface { RegistrationHandler() *Handler @@ -136,7 +139,17 @@ func (h *Handler) NewRegistrationFlow(w http.ResponseWriter, r *http.Request, ft f.SessionTokenExchangeCode = e.InitCode } - for _, s := range h.d.RegistrationStrategies(r.Context()) { + var strategyFilters []StrategyFilter + if rawOrg := r.URL.Query().Get("organization"); rawOrg != "" { + orgID, err := uuid.FromString(rawOrg) + if err != nil { + h.d.Logger().WithError(err).Warnf("ignoring invalid UUID %q in query parameter `organization`", rawOrg) + } else { + f.OrganizationID = uuid.NullUUID{UUID: orgID, Valid: true} + strategyFilters = []StrategyFilter{func(s Strategy) bool { return s.ID() == identity.CredentialsTypeOIDC }} + } + } + for _, s := range h.d.RegistrationStrategies(r.Context(), strategyFilters...) { if err := s.PopulateRegistrationMethod(r, f); err != nil { return nil, err } @@ -265,6 +278,10 @@ type createBrowserRegistrationFlow struct { // required: false // in: query AfterVerificationReturnTo string `json:"after_verification_return_to"` + + // required: false + // in: query + Organization string `json:"organization"` } // swagger:route GET /self-service/registration/browser frontend createBrowserRegistrationFlow diff --git a/selfservice/flow/registration/hook.go b/selfservice/flow/registration/hook.go index a10d2a4daa07..20538ccfe1e6 100644 --- a/selfservice/flow/registration/hook.go +++ b/selfservice/flow/registration/hook.go @@ -9,6 +9,7 @@ import ( "net/http" "time" + "github.com/julienschmidt/httprouter" "go.opentelemetry.io/otel/trace" "github.com/ory/kratos/selfservice/sessiontokenexchange" @@ -167,7 +168,9 @@ func (e *HookExecutor) PostRegistrationHook(w http.ResponseWriter, r *http.Reque trace.SpanFromContext(r.Context()).AddEvent(events.NewRegistrationSucceeded(r.Context(), i.ID, string(a.Type), a.Active.String(), provider)) s := session.NewInactiveSession() - s.CompletedLoginForWithProvider(ct, identity.AuthenticatorAssuranceLevel1, provider) + + s.CompletedLoginForWithProvider(ct, identity.AuthenticatorAssuranceLevel1, provider, + httprouter.ParamsFromContext(r.Context()).ByName("organization")) if err := s.Activate(r, i, c, time.Now().UTC()); err != nil { return err } diff --git a/selfservice/flow/registration/strategy.go b/selfservice/flow/registration/strategy.go index 7fa8efd78cd2..7524eb350764 100644 --- a/selfservice/flow/registration/strategy.go +++ b/selfservice/flow/registration/strategy.go @@ -51,7 +51,9 @@ func (s Strategies) RegisterPublicRoutes(r *x.RouterPublic) { } } +type StrategyFilter func(strategy Strategy) bool + type StrategyProvider interface { - RegistrationStrategies(ctx context.Context) Strategies + RegistrationStrategies(ctx context.Context, filters ...StrategyFilter) Strategies AllRegistrationStrategies() Strategies } diff --git a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=body_is_empty.json b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=body_is_empty.json index 5cc825657c23..06206d1517e8 100644 --- a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=body_is_empty.json +++ b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=body_is_empty.json @@ -47,5 +47,6 @@ "admin": "data" }, "created_at": "0001-01-01T00:00:00Z", - "updated_at": "0001-01-01T00:00:00Z" + "updated_at": "0001-01-01T00:00:00Z", + "organization_id": null } diff --git a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_admin_metadata.json b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_admin_metadata.json index 5cc825657c23..06206d1517e8 100644 --- a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_admin_metadata.json +++ b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_admin_metadata.json @@ -47,5 +47,6 @@ "admin": "data" }, "created_at": "0001-01-01T00:00:00Z", - "updated_at": "0001-01-01T00:00:00Z" + "updated_at": "0001-01-01T00:00:00Z", + "organization_id": null } diff --git a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_public_metadata.json b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_public_metadata.json index 47d0200bd9e2..d3f2123e251d 100644 --- a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_public_metadata.json +++ b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_public_metadata.json @@ -47,5 +47,6 @@ "admin": "data" }, "created_at": "0001-01-01T00:00:00Z", - "updated_at": "0001-01-01T00:00:00Z" + "updated_at": "0001-01-01T00:00:00Z", + "organization_id": null } diff --git a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_recovery_addresses.json b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_recovery_addresses.json index 5468c64f6e6d..6ac68c9dad02 100644 --- a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_recovery_addresses.json +++ b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_recovery_addresses.json @@ -47,5 +47,6 @@ "admin": "data" }, "created_at": "0001-01-01T00:00:00Z", - "updated_at": "0001-01-01T00:00:00Z" + "updated_at": "0001-01-01T00:00:00Z", + "organization_id": null } diff --git a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_state.json b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_state.json index a29fca67072b..d2c8048eca70 100644 --- a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_state.json +++ b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_state.json @@ -47,5 +47,6 @@ "admin": "data" }, "created_at": "0001-01-01T00:00:00Z", - "updated_at": "0001-01-01T00:00:00Z" + "updated_at": "0001-01-01T00:00:00Z", + "organization_id": null } diff --git a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_traits.json b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_traits.json index eee811bea641..12f86f05c436 100644 --- a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_traits.json +++ b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_traits.json @@ -47,5 +47,6 @@ "admin": "data" }, "created_at": "0001-01-01T00:00:00Z", - "updated_at": "0001-01-01T00:00:00Z" + "updated_at": "0001-01-01T00:00:00Z", + "organization_id": null } diff --git a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_verified_addresses.json b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_verified_addresses.json index aac455d717b6..52f6e02e1025 100644 --- a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_verified_addresses.json +++ b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_has_updated_verified_addresses.json @@ -47,5 +47,6 @@ "admin": "data" }, "created_at": "0001-01-01T00:00:00Z", - "updated_at": "0001-01-01T00:00:00Z" + "updated_at": "0001-01-01T00:00:00Z", + "organization_id": null } diff --git a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_is_present_but_empty.json b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_is_present_but_empty.json index 5cc825657c23..06206d1517e8 100644 --- a/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_is_present_but_empty.json +++ b/selfservice/hook/.snapshots/TestWebHooks-update_identity_fields-case=update_identity_fields-case=identity_is_present_but_empty.json @@ -47,5 +47,6 @@ "admin": "data" }, "created_at": "0001-01-01T00:00:00Z", - "updated_at": "0001-01-01T00:00:00Z" + "updated_at": "0001-01-01T00:00:00Z", + "organization_id": null } diff --git a/selfservice/strategy/code/strategy.go b/selfservice/strategy/code/strategy.go index 229c6dfaf8d1..6044db79de0f 100644 --- a/selfservice/strategy/code/strategy.go +++ b/selfservice/strategy/code/strategy.go @@ -118,8 +118,8 @@ type ( } ) -func NewStrategy(deps strategyDependencies) *Strategy { - return &Strategy{deps: deps, dx: decoderx.NewHTTP()} +func NewStrategy(deps any) *Strategy { + return &Strategy{deps: deps.(strategyDependencies), dx: decoderx.NewHTTP()} } func (s *Strategy) ID() identity.CredentialsType { diff --git a/selfservice/strategy/link/strategy.go b/selfservice/strategy/link/strategy.go index da66e1816bf5..f5a0326b9d0b 100644 --- a/selfservice/strategy/link/strategy.go +++ b/selfservice/strategy/link/strategy.go @@ -83,8 +83,8 @@ type ( } ) -func NewStrategy(d strategyDependencies) *Strategy { - return &Strategy{d: d, dx: decoderx.NewHTTP()} +func NewStrategy(d any) *Strategy { + return &Strategy{d: d.(strategyDependencies), dx: decoderx.NewHTTP()} } func (s *Strategy) NodeGroup() node.UiNodeGroup { diff --git a/selfservice/strategy/lookup/strategy.go b/selfservice/strategy/lookup/strategy.go index 170c370509c1..13c233913f18 100644 --- a/selfservice/strategy/lookup/strategy.go +++ b/selfservice/strategy/lookup/strategy.go @@ -27,7 +27,7 @@ import ( var _ settings.Strategy = new(Strategy) var _ identity.ActiveCredentialsCounter = new(Strategy) -type registrationStrategyDependencies interface { +type lookupStrategyDependencies interface { x.LoggingProvider x.WriterProvider x.CSRFTokenGeneratorProvider @@ -65,13 +65,13 @@ type registrationStrategyDependencies interface { } type Strategy struct { - d registrationStrategyDependencies + d lookupStrategyDependencies hd *decoderx.HTTP } -func NewStrategy(d registrationStrategyDependencies) *Strategy { +func NewStrategy(d any) *Strategy { return &Strategy{ - d: d, + d: d.(lookupStrategyDependencies), hd: decoderx.NewHTTP(), } } diff --git a/selfservice/strategy/oidc/provider_apple.go b/selfservice/strategy/oidc/provider_apple.go index 74affe5afb3d..9a83429152d3 100644 --- a/selfservice/strategy/oidc/provider_apple.go +++ b/selfservice/strategy/oidc/provider_apple.go @@ -27,7 +27,7 @@ type ProviderApple struct { func NewProviderApple( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { config.IssuerURL = "https://appleid.apple.com" return &ProviderApple{ diff --git a/selfservice/strategy/oidc/provider_auth0.go b/selfservice/strategy/oidc/provider_auth0.go index 3b9f7a3dff5f..302c61eaf48e 100644 --- a/selfservice/strategy/oidc/provider_auth0.go +++ b/selfservice/strategy/oidc/provider_auth0.go @@ -32,7 +32,7 @@ type ProviderAuth0 struct { func NewProviderAuth0( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderAuth0{ ProviderGenericOIDC: &ProviderGenericOIDC{ diff --git a/selfservice/strategy/oidc/provider_config.go b/selfservice/strategy/oidc/provider_config.go index 45fc0734ae91..4c8275c4f709 100644 --- a/selfservice/strategy/oidc/provider_config.go +++ b/selfservice/strategy/oidc/provider_config.go @@ -104,12 +104,21 @@ type Configuration struct { // // More information: https://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter RequestedClaims json.RawMessage `json:"requested_claims"` + + // An optional organization ID that this provider belongs to. + // This parameter is only effective in the Ory Network. + OrganizationID string `json:"organization_id"` } func (p Configuration) Redir(public *url.URL) string { - return urlx.AppendPaths(public, - strings.Replace(RouteCallback, ":provider", p.ID, 1), - ).String() + if p.OrganizationID != "" { + route := RouteOrganizationCallback + route = strings.Replace(route, ":provider", p.ID, 1) + route = strings.Replace(route, ":organization", p.OrganizationID, 1) + return urlx.AppendPaths(public, route).String() + } + + return urlx.AppendPaths(public, strings.Replace(RouteCallback, ":provider", p.ID, 1)).String() } type ConfigurationCollection struct { @@ -121,7 +130,7 @@ type ConfigurationCollection struct { // // If you add a provider here, please also add a test to // provider_private_net_test.go -var supportedProviders = map[string]func(config *Configuration, reg dependencies) Provider{ +var supportedProviders = map[string]func(config *Configuration, reg Dependencies) Provider{ "generic": NewProviderGenericOIDC, "google": NewProviderGoogle, "github": NewProviderGitHub, @@ -143,7 +152,7 @@ var supportedProviders = map[string]func(config *Configuration, reg dependencies "lark": NewProviderLark, } -func (c ConfigurationCollection) Provider(id string, reg dependencies) (Provider, error) { +func (c ConfigurationCollection) Provider(id string, reg Dependencies) (Provider, error) { for k := range c.Providers { p := c.Providers[k] if p.ID == id { diff --git a/selfservice/strategy/oidc/provider_dingtalk.go b/selfservice/strategy/oidc/provider_dingtalk.go index 7b4a835e5734..36469e6e7c23 100644 --- a/selfservice/strategy/oidc/provider_dingtalk.go +++ b/selfservice/strategy/oidc/provider_dingtalk.go @@ -22,12 +22,12 @@ import ( type ProviderDingTalk struct { config *Configuration - reg dependencies + reg Dependencies } func NewProviderDingTalk( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderDingTalk{ config: config, diff --git a/selfservice/strategy/oidc/provider_discord.go b/selfservice/strategy/oidc/provider_discord.go index e48ce351a6dc..181e7df6d322 100644 --- a/selfservice/strategy/oidc/provider_discord.go +++ b/selfservice/strategy/oidc/provider_discord.go @@ -21,12 +21,12 @@ import ( type ProviderDiscord struct { config *Configuration - reg dependencies + reg Dependencies } func NewProviderDiscord( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderDiscord{ config: config, diff --git a/selfservice/strategy/oidc/provider_facebook.go b/selfservice/strategy/oidc/provider_facebook.go index 7cf89538f978..32bf1f35c0fa 100644 --- a/selfservice/strategy/oidc/provider_facebook.go +++ b/selfservice/strategy/oidc/provider_facebook.go @@ -30,7 +30,7 @@ type ProviderFacebook struct { func NewProviderFacebook( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { config.IssuerURL = "https://www.facebook.com" return &ProviderFacebook{ diff --git a/selfservice/strategy/oidc/provider_generic_oidc.go b/selfservice/strategy/oidc/provider_generic_oidc.go index 59d86f985994..a0b551649ae7 100644 --- a/selfservice/strategy/oidc/provider_generic_oidc.go +++ b/selfservice/strategy/oidc/provider_generic_oidc.go @@ -21,12 +21,12 @@ var _ Provider = new(ProviderGenericOIDC) type ProviderGenericOIDC struct { p *gooidc.Provider config *Configuration - reg dependencies + reg Dependencies } func NewProviderGenericOIDC( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderGenericOIDC{ config: config, diff --git a/selfservice/strategy/oidc/provider_github.go b/selfservice/strategy/oidc/provider_github.go index 8b8b97ee5f83..c805c593b4e0 100644 --- a/selfservice/strategy/oidc/provider_github.go +++ b/selfservice/strategy/oidc/provider_github.go @@ -24,12 +24,12 @@ import ( type ProviderGitHub struct { config *Configuration - reg dependencies + reg Dependencies } func NewProviderGitHub( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderGitHub{ config: config, diff --git a/selfservice/strategy/oidc/provider_github_app.go b/selfservice/strategy/oidc/provider_github_app.go index f48de9664547..703ba494df2c 100644 --- a/selfservice/strategy/oidc/provider_github_app.go +++ b/selfservice/strategy/oidc/provider_github_app.go @@ -21,12 +21,12 @@ import ( type ProviderGitHubApp struct { config *Configuration - reg dependencies + reg Dependencies } func NewProviderGitHubApp( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderGitHubApp{ config: config, diff --git a/selfservice/strategy/oidc/provider_gitlab.go b/selfservice/strategy/oidc/provider_gitlab.go index fde2506e0a63..f7493367345f 100644 --- a/selfservice/strategy/oidc/provider_gitlab.go +++ b/selfservice/strategy/oidc/provider_gitlab.go @@ -31,7 +31,7 @@ type ProviderGitLab struct { func NewProviderGitLab( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderGitLab{ ProviderGenericOIDC: &ProviderGenericOIDC{ diff --git a/selfservice/strategy/oidc/provider_google.go b/selfservice/strategy/oidc/provider_google.go index 54adda2b96c3..c1ccdf505383 100644 --- a/selfservice/strategy/oidc/provider_google.go +++ b/selfservice/strategy/oidc/provider_google.go @@ -20,7 +20,7 @@ type ProviderGoogle struct { func NewProviderGoogle( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { config.IssuerURL = "https://accounts.google.com" return &ProviderGoogle{ diff --git a/selfservice/strategy/oidc/provider_lark.go b/selfservice/strategy/oidc/provider_lark.go index b239a207c095..52902dc20e8c 100644 --- a/selfservice/strategy/oidc/provider_lark.go +++ b/selfservice/strategy/oidc/provider_lark.go @@ -31,7 +31,7 @@ var ( func NewProviderLark( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderLark{ &ProviderGenericOIDC{ diff --git a/selfservice/strategy/oidc/provider_linkedin.go b/selfservice/strategy/oidc/provider_linkedin.go index a9dde8ce37e3..052542d2b00a 100644 --- a/selfservice/strategy/oidc/provider_linkedin.go +++ b/selfservice/strategy/oidc/provider_linkedin.go @@ -65,12 +65,12 @@ const ( type ProviderLinkedIn struct { config *Configuration - reg dependencies + reg Dependencies } func NewProviderLinkedIn( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderLinkedIn{ config: config, diff --git a/selfservice/strategy/oidc/provider_microsoft.go b/selfservice/strategy/oidc/provider_microsoft.go index af664f7f8aca..3e31e505b358 100644 --- a/selfservice/strategy/oidc/provider_microsoft.go +++ b/selfservice/strategy/oidc/provider_microsoft.go @@ -29,7 +29,7 @@ type ProviderMicrosoft struct { func NewProviderMicrosoft( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderMicrosoft{ ProviderGenericOIDC: &ProviderGenericOIDC{ diff --git a/selfservice/strategy/oidc/provider_netid.go b/selfservice/strategy/oidc/provider_netid.go index a919c177728f..f8f0023878ef 100644 --- a/selfservice/strategy/oidc/provider_netid.go +++ b/selfservice/strategy/oidc/provider_netid.go @@ -34,7 +34,7 @@ type ProviderNetID struct { func NewProviderNetID( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { config.IssuerURL = fmt.Sprintf("%s://%s/", defaultBrokerScheme, defaultBrokerHost) if !stringslice.Has(config.Scope, gooidc.ScopeOpenID) { diff --git a/selfservice/strategy/oidc/provider_patreon.go b/selfservice/strategy/oidc/provider_patreon.go index dbd740ff88bf..abe1eeffd805 100644 --- a/selfservice/strategy/oidc/provider_patreon.go +++ b/selfservice/strategy/oidc/provider_patreon.go @@ -20,7 +20,7 @@ import ( type ProviderPatreon struct { config *Configuration - reg dependencies + reg Dependencies } type PatreonIdentityResponse struct { @@ -39,7 +39,7 @@ type PatreonIdentityResponse struct { func NewProviderPatreon( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderPatreon{ config: config, diff --git a/selfservice/strategy/oidc/provider_slack.go b/selfservice/strategy/oidc/provider_slack.go index 951b7fab1874..7c7e26c99da4 100644 --- a/selfservice/strategy/oidc/provider_slack.go +++ b/selfservice/strategy/oidc/provider_slack.go @@ -21,12 +21,12 @@ import ( type ProviderSlack struct { config *Configuration - reg dependencies + reg Dependencies } func NewProviderSlack( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderSlack{ config: config, diff --git a/selfservice/strategy/oidc/provider_spotify.go b/selfservice/strategy/oidc/provider_spotify.go index 3c0d95ea043d..d68671f9974e 100644 --- a/selfservice/strategy/oidc/provider_spotify.go +++ b/selfservice/strategy/oidc/provider_spotify.go @@ -24,12 +24,12 @@ import ( type ProviderSpotify struct { config *Configuration - reg dependencies + reg Dependencies } func NewProviderSpotify( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderSpotify{ config: config, diff --git a/selfservice/strategy/oidc/provider_test.go b/selfservice/strategy/oidc/provider_test.go index 74fdb05031fc..7c0de7c55138 100644 --- a/selfservice/strategy/oidc/provider_test.go +++ b/selfservice/strategy/oidc/provider_test.go @@ -25,14 +25,14 @@ type TestProvider struct { *ProviderGenericOIDC } -func NewTestProvider(c *Configuration, reg dependencies) Provider { +func NewTestProvider(c *Configuration, reg Dependencies) Provider { return &TestProvider{ ProviderGenericOIDC: NewProviderGenericOIDC(c, reg).(*ProviderGenericOIDC), } } func RegisterTestProvider(id string) func() { - supportedProviders[id] = func(c *Configuration, reg dependencies) Provider { + supportedProviders[id] = func(c *Configuration, reg Dependencies) Provider { return NewTestProvider(c, reg) } return func() { diff --git a/selfservice/strategy/oidc/provider_vk.go b/selfservice/strategy/oidc/provider_vk.go index 6d89170d77a1..995eed6fbe07 100644 --- a/selfservice/strategy/oidc/provider_vk.go +++ b/selfservice/strategy/oidc/provider_vk.go @@ -21,12 +21,12 @@ import ( type ProviderVK struct { config *Configuration - reg dependencies + reg Dependencies } func NewProviderVK( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderVK{ config: config, diff --git a/selfservice/strategy/oidc/provider_yandex.go b/selfservice/strategy/oidc/provider_yandex.go index 4c93a13a196e..dfb9267f8793 100644 --- a/selfservice/strategy/oidc/provider_yandex.go +++ b/selfservice/strategy/oidc/provider_yandex.go @@ -19,12 +19,12 @@ import ( type ProviderYandex struct { config *Configuration - reg dependencies + reg Dependencies } func NewProviderYandex( config *Configuration, - reg dependencies, + reg Dependencies, ) Provider { return &ProviderYandex{ config: config, diff --git a/selfservice/strategy/oidc/strategy.go b/selfservice/strategy/oidc/strategy.go index d772bfd0f198..70fa10585d18 100644 --- a/selfservice/strategy/oidc/strategy.go +++ b/selfservice/strategy/oidc/strategy.go @@ -56,13 +56,14 @@ import ( const ( RouteBase = "/self-service/methods/oidc" - RouteAuth = RouteBase + "/auth/:flow" - RouteCallback = RouteBase + "/callback/:provider" + RouteAuth = RouteBase + "/auth/:flow" + RouteCallback = RouteBase + "/callback/:provider" + RouteOrganizationCallback = RouteBase + "/organization/:organization/callback/:provider" ) var _ identity.ActiveCredentialsCounter = new(Strategy) -type dependencies interface { +type Dependencies interface { errorx.ManagementProvider config.Provider @@ -119,12 +120,12 @@ func isForced(req interface{}) bool { // Strategy implements selfservice.LoginStrategy, selfservice.RegistrationStrategy and selfservice.SettingsStrategy. // It supports login, registration and settings via OpenID Providers. type Strategy struct { - d dependencies + d Dependencies validator *schema.Validator dec *decoderx.HTTP } -type authCodeContainer struct { +type AuthCodeContainer struct { FlowID string `json:"flow_id"` State string `json:"state"` Traits json.RawMessage `json:"traits"` @@ -197,7 +198,7 @@ func (s *Strategy) CountActiveMultiFactorCredentials(cc map[identity.Credentials } func (s *Strategy) setRoutes(r *x.RouterPublic) { - wrappedHandleCallback := strategy.IsDisabled(s.d, s.ID().String(), s.handleCallback) + wrappedHandleCallback := strategy.IsDisabled(s.d, s.ID().String(), s.HandleCallback) if handle, _, _ := r.Lookup("GET", RouteCallback); handle == nil { r.GET(RouteCallback, wrappedHandleCallback) } @@ -236,9 +237,9 @@ func (s *Strategy) redirectToGET(w http.ResponseWriter, r *http.Request, _ httpr http.Redirect(w, r, dest.String(), http.StatusFound) } -func NewStrategy(d dependencies) *Strategy { +func NewStrategy(d any) *Strategy { return &Strategy{ - d: d, + d: d.(Dependencies), validator: schema.NewValidator(), } } @@ -282,7 +283,7 @@ func (s *Strategy) validateFlow(ctx context.Context, r *http.Request, rid uuid.U return ar, err // this must return the error } -func (s *Strategy) validateCallback(w http.ResponseWriter, r *http.Request) (flow.Flow, *authCodeContainer, error) { +func (s *Strategy) ValidateCallback(w http.ResponseWriter, r *http.Request) (flow.Flow, *AuthCodeContainer, error) { var ( codeParam = stringsx.Coalesce(r.URL.Query().Get("code"), r.URL.Query().Get("authCode")) stateParam = r.URL.Query().Get("state") @@ -307,7 +308,7 @@ func (s *Strategy) validateCallback(w http.ResponseWriter, r *http.Request) (flo return nil, nil, err } - cntnr := authCodeContainer{} + cntnr := AuthCodeContainer{} if f.GetType() == flow.TypeBrowser || !hasSessionTokenCode { if _, err := s.d.ContinuityManager().Continue(r.Context(), w, r, sessionName, continuity.WithPayload(&cntnr)); err != nil { return nil, nil, err @@ -375,13 +376,17 @@ func (s *Strategy) alreadyAuthenticated(w http.ResponseWriter, r *http.Request, return false, nil } -func (s *Strategy) handleCallback(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { +func (s *Strategy) HandleCallback(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { var ( code = stringsx.Coalesce(r.URL.Query().Get("code"), r.URL.Query().Get("authCode")) pid = ps.ByName("provider") ) - req, cntnr, err := s.validateCallback(w, r) + ctx := r.Context() + ctx = context.WithValue(ctx, httprouter.ParamsKey, ps) + r = r.WithContext(ctx) + + req, cntnr, err := s.ValidateCallback(w, r) if err != nil { if req != nil { s.forwardError(w, r, req, s.handleError(w, r, req, pid, nil, err)) diff --git a/selfservice/strategy/oidc/strategy_login.go b/selfservice/strategy/oidc/strategy_login.go index 14d44702bb75..5150eabcda52 100644 --- a/selfservice/strategy/oidc/strategy_login.go +++ b/selfservice/strategy/oidc/strategy_login.go @@ -9,6 +9,7 @@ import ( "net/http" "time" + "github.com/julienschmidt/httprouter" "golang.org/x/oauth2" "github.com/gofrs/uuid" @@ -101,7 +102,7 @@ type UpdateLoginFlowWithOidcMethod struct { IDTokenNonce string `json:"id_token_nonce,omitempty"` } -func (s *Strategy) processLogin(w http.ResponseWriter, r *http.Request, loginFlow *login.Flow, token *oauth2.Token, claims *Claims, provider Provider, container *authCodeContainer) (*registration.Flow, error) { +func (s *Strategy) processLogin(w http.ResponseWriter, r *http.Request, loginFlow *login.Flow, token *oauth2.Token, claims *Claims, provider Provider, container *AuthCodeContainer) (*registration.Flow, error) { i, c, err := s.d.PrivilegedIdentityPool().FindByCredentialsIdentifier(r.Context(), identity.CredentialsTypeOIDC, identity.OIDCUniqueID(provider.Config().ID, claims.Subject)) if err != nil { if errors.Is(err, sqlcon.ErrNoRows) { @@ -141,6 +142,7 @@ func (s *Strategy) processLogin(w http.ResponseWriter, r *http.Request, loginFlo return nil, s.handleError(w, r, loginFlow, provider.Config().ID, nil, err) } + registrationFlow.OrganizationID = loginFlow.OrganizationID registrationFlow.IDToken = loginFlow.IDToken registrationFlow.RawIDTokenNonce = loginFlow.RawIDTokenNonce registrationFlow.RequestURL, err = x.TakeOverReturnToParameter(loginFlow.RequestURL, registrationFlow.RequestURL) @@ -164,7 +166,8 @@ func (s *Strategy) processLogin(w http.ResponseWriter, r *http.Request, loginFlo } sess := session.NewInactiveSession() - sess.CompletedLoginForWithProvider(s.ID(), identity.AuthenticatorAssuranceLevel1, provider.Config().ID) + sess.CompletedLoginForWithProvider(s.ID(), identity.AuthenticatorAssuranceLevel1, provider.Config().ID, + httprouter.ParamsFromContext(r.Context()).ByName("organization")) for _, c := range oidcCredentials.Providers { if c.Subject == claims.Subject && c.Provider == provider.Config().ID { if err = s.d.LoginHookExecutor().PostLoginHook(w, r, node.OpenIDConnectGroup, loginFlow, i, sess, provider.Config().ID); err != nil { @@ -225,7 +228,7 @@ func (s *Strategy) Login(w http.ResponseWriter, r *http.Request, f *login.Flow, if err != nil { return nil, s.handleError(w, r, f, pid, nil, err) } - _, err = s.processLogin(w, r, f, nil, claims, provider, &authCodeContainer{ + _, err = s.processLogin(w, r, f, nil, claims, provider, &AuthCodeContainer{ FlowID: f.ID.String(), Traits: p.Traits, }) @@ -240,7 +243,7 @@ func (s *Strategy) Login(w http.ResponseWriter, r *http.Request, f *login.Flow, state.setCode(code.InitCode) } if err := s.d.ContinuityManager().Pause(r.Context(), w, r, sessionName, - continuity.WithPayload(&authCodeContainer{ + continuity.WithPayload(&AuthCodeContainer{ State: state.String(), FlowID: f.ID.String(), Traits: p.Traits, diff --git a/selfservice/strategy/oidc/strategy_registration.go b/selfservice/strategy/oidc/strategy_registration.go index 15b42ac56c6f..13c6a448c047 100644 --- a/selfservice/strategy/oidc/strategy_registration.go +++ b/selfservice/strategy/oidc/strategy_registration.go @@ -10,6 +10,9 @@ import ( "strings" "time" + "github.com/gofrs/uuid" + "github.com/julienschmidt/httprouter" + "github.com/ory/x/sqlxx" "github.com/ory/herodot" @@ -192,7 +195,7 @@ func (s *Strategy) Register(w http.ResponseWriter, r *http.Request, f *registrat if err != nil { return s.handleError(w, r, f, pid, nil, err) } - _, err = s.processRegistration(w, r, f, nil, claims, provider, &authCodeContainer{ + _, err = s.processRegistration(w, r, f, nil, claims, provider, &AuthCodeContainer{ FlowID: f.ID.String(), Traits: p.Traits, TransientPayload: f.TransientPayload, @@ -208,7 +211,7 @@ func (s *Strategy) Register(w http.ResponseWriter, r *http.Request, f *registrat state.setCode(code.InitCode) } if err := s.d.ContinuityManager().Pause(r.Context(), w, r, sessionName, - continuity.WithPayload(&authCodeContainer{ + continuity.WithPayload(&AuthCodeContainer{ State: state.String(), FlowID: f.ID.String(), Traits: p.Traits, @@ -262,7 +265,7 @@ func (s *Strategy) registrationToLogin(w http.ResponseWriter, r *http.Request, r return lf, nil } -func (s *Strategy) processRegistration(w http.ResponseWriter, r *http.Request, rf *registration.Flow, token *oauth2.Token, claims *Claims, provider Provider, container *authCodeContainer, idToken string) (*login.Flow, error) { +func (s *Strategy) processRegistration(w http.ResponseWriter, r *http.Request, rf *registration.Flow, token *oauth2.Token, claims *Claims, provider Provider, container *AuthCodeContainer, idToken string) (*login.Flow, error) { if _, _, err := s.d.PrivilegedIdentityPool().FindByCredentialsIdentifier(r.Context(), identity.CredentialsTypeOIDC, identity.OIDCUniqueID(provider.Config().ID, claims.Subject)); err == nil { // If the identity already exists, we should perform the login flow instead. @@ -339,7 +342,7 @@ func (s *Strategy) processRegistration(w http.ResponseWriter, r *http.Request, r } } - creds, err := identity.NewCredentialsOIDC(it, cat, crt, provider.Config().ID, claims.Subject) + creds, err := identity.NewCredentialsOIDC(it, cat, crt, provider.Config().ID, claims.Subject, provider.Config().OrganizationID) if err != nil { return nil, s.handleError(w, r, rf, provider.Config().ID, i.Traits, err) } @@ -352,7 +355,7 @@ func (s *Strategy) processRegistration(w http.ResponseWriter, r *http.Request, r return nil, nil } -func (s *Strategy) createIdentity(w http.ResponseWriter, r *http.Request, a *registration.Flow, claims *Claims, provider Provider, container *authCodeContainer, jn *bytes.Buffer) (*identity.Identity, []VerifiedAddress, error) { +func (s *Strategy) createIdentity(w http.ResponseWriter, r *http.Request, a *registration.Flow, claims *Claims, provider Provider, container *AuthCodeContainer, jn *bytes.Buffer) (*identity.Identity, []VerifiedAddress, error) { var jsonClaims bytes.Buffer if err := json.NewEncoder(&jsonClaims).Encode(claims); err != nil { return nil, nil, s.handleError(w, r, a, provider.Config().ID, nil, err) @@ -387,6 +390,10 @@ func (s *Strategy) createIdentity(w http.ResponseWriter, r *http.Request, a *reg return nil, nil, s.handleError(w, r, a, provider.Config().ID, i.Traits, err) } + if orgID := httprouter.ParamsFromContext(r.Context()).ByName("organization"); orgID != "" { + i.OrganizationID = uuid.NullUUID{UUID: x.ParseUUID(orgID), Valid: true} + } + s.d.Logger(). WithRequest(r). WithField("oidc_provider", provider.Config().ID). @@ -397,7 +404,7 @@ func (s *Strategy) createIdentity(w http.ResponseWriter, r *http.Request, a *reg return i, va, nil } -func (s *Strategy) setTraits(w http.ResponseWriter, r *http.Request, a *registration.Flow, claims *Claims, provider Provider, container *authCodeContainer, evaluated string, i *identity.Identity) error { +func (s *Strategy) setTraits(w http.ResponseWriter, r *http.Request, a *registration.Flow, claims *Claims, provider Provider, container *AuthCodeContainer, evaluated string, i *identity.Identity) error { jsonTraits := gjson.Get(evaluated, "identity.traits") if !jsonTraits.IsObject() { return errors.WithStack(herodot.ErrInternalServerError.WithReasonf("OpenID Connect Jsonnet mapper did not return an object for key identity.traits. Please check your Jsonnet code!")) diff --git a/selfservice/strategy/oidc/strategy_settings.go b/selfservice/strategy/oidc/strategy_settings.go index 1866cd82aaab..513f5cccdabe 100644 --- a/selfservice/strategy/oidc/strategy_settings.go +++ b/selfservice/strategy/oidc/strategy_settings.go @@ -359,7 +359,7 @@ func (s *Strategy) initLinkProvider(w http.ResponseWriter, r *http.Request, ctxU state := generateState(ctxUpdate.Flow.ID.String()).String() if err := s.d.ContinuityManager().Pause(r.Context(), w, r, sessionName, - continuity.WithPayload(&authCodeContainer{ + continuity.WithPayload(&AuthCodeContainer{ State: state, FlowID: ctxUpdate.Flow.ID.String(), Traits: p.Traits, @@ -416,7 +416,7 @@ func (s *Strategy) linkProvider(w http.ResponseWriter, r *http.Request, ctxUpdat creds, err := i.ParseCredentials(s.ID(), &conf) if errors.Is(err, herodot.ErrNotFound) { var err error - if creds, err = identity.NewCredentialsOIDC(it, cat, crt, provider.Config().ID, claims.Subject); err != nil { + if creds, err = identity.NewCredentialsOIDC(it, cat, crt, provider.Config().ID, claims.Subject, ""); err != nil { return s.handleSettingsError(w, r, ctxUpdate, p, err) } } else if err != nil { diff --git a/selfservice/strategy/password/strategy.go b/selfservice/strategy/password/strategy.go index 2993c428b701..bb750bc9ef80 100644 --- a/selfservice/strategy/password/strategy.go +++ b/selfservice/strategy/password/strategy.go @@ -76,9 +76,9 @@ type Strategy struct { hd *decoderx.HTTP } -func NewStrategy(d registrationStrategyDependencies) *Strategy { +func NewStrategy(d any) *Strategy { return &Strategy{ - d: d, + d: d.(registrationStrategyDependencies), v: validator.New(), hd: decoderx.NewHTTP(), } diff --git a/selfservice/strategy/profile/strategy.go b/selfservice/strategy/profile/strategy.go index e94d779aef61..5b8d7f368306 100644 --- a/selfservice/strategy/profile/strategy.go +++ b/selfservice/strategy/profile/strategy.go @@ -68,8 +68,8 @@ type ( } ) -func NewStrategy(d strategyDependencies) *Strategy { - return &Strategy{d: d, dc: decoderx.NewHTTP()} +func NewStrategy(d any) *Strategy { + return &Strategy{d: d.(strategyDependencies), dc: decoderx.NewHTTP()} } func (s *Strategy) SettingsStrategyID() string { diff --git a/selfservice/strategy/totp/strategy.go b/selfservice/strategy/totp/strategy.go index bb4da1d3ec2d..bcaf09069053 100644 --- a/selfservice/strategy/totp/strategy.go +++ b/selfservice/strategy/totp/strategy.go @@ -28,7 +28,7 @@ var _ login.Strategy = new(Strategy) var _ settings.Strategy = new(Strategy) var _ identity.ActiveCredentialsCounter = new(Strategy) -type registrationStrategyDependencies interface { +type totpStrategyDependencies interface { x.LoggingProvider x.WriterProvider x.CSRFTokenGeneratorProvider @@ -67,13 +67,13 @@ type registrationStrategyDependencies interface { } type Strategy struct { - d registrationStrategyDependencies + d totpStrategyDependencies hd *decoderx.HTTP } -func NewStrategy(d registrationStrategyDependencies) *Strategy { +func NewStrategy(d any) *Strategy { return &Strategy{ - d: d, + d: d.(totpStrategyDependencies), hd: decoderx.NewHTTP(), } } diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=browser.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=browser.json index 49c3fede7254..e6376bbf7d9e 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=browser.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=browser.json @@ -1,4 +1,5 @@ { + "organization_id": null, "type": "browser", "ui": { "method": "POST", diff --git a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=spa.json b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=spa.json index 49c3fede7254..e6376bbf7d9e 100644 --- a/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=spa.json +++ b/selfservice/strategy/webauthn/.snapshots/TestCompleteLogin-flow=passwordless-case=should_fail_if_webauthn_login_is_invalid-type=spa.json @@ -1,4 +1,5 @@ { + "organization_id": null, "type": "browser", "ui": { "method": "POST", diff --git a/selfservice/strategy/webauthn/strategy.go b/selfservice/strategy/webauthn/strategy.go index 051267efc9ba..aa4529cda620 100644 --- a/selfservice/strategy/webauthn/strategy.go +++ b/selfservice/strategy/webauthn/strategy.go @@ -27,7 +27,7 @@ var _ login.Strategy = new(Strategy) var _ settings.Strategy = new(Strategy) var _ identity.ActiveCredentialsCounter = new(Strategy) -type registrationStrategyDependencies interface { +type webauthnStrategyDependencies interface { x.LoggingProvider x.WriterProvider x.CSRFTokenGeneratorProvider @@ -67,13 +67,13 @@ type registrationStrategyDependencies interface { } type Strategy struct { - d registrationStrategyDependencies + d webauthnStrategyDependencies hd *decoderx.HTTP } -func NewStrategy(d registrationStrategyDependencies) *Strategy { +func NewStrategy(d any) *Strategy { return &Strategy{ - d: d, + d: d.(webauthnStrategyDependencies), hd: decoderx.NewHTTP(), } } diff --git a/session/session.go b/session/session.go index ceb792f66b2e..74204be4215c 100644 --- a/session/session.go +++ b/session/session.go @@ -168,8 +168,14 @@ func (s *Session) CompletedLoginFor(method identity.CredentialsType, aal identit s.AMR = append(s.AMR, AuthenticationMethod{Method: method, AAL: aal, CompletedAt: time.Now().UTC()}) } -func (s *Session) CompletedLoginForWithProvider(method identity.CredentialsType, aal identity.AuthenticatorAssuranceLevel, providerID string) { - s.AMR = append(s.AMR, AuthenticationMethod{Method: method, AAL: aal, Provider: providerID, CompletedAt: time.Now().UTC()}) +func (s *Session) CompletedLoginForWithProvider(method identity.CredentialsType, aal identity.AuthenticatorAssuranceLevel, providerID string, organizationID string) { + s.AMR = append(s.AMR, AuthenticationMethod{ + Method: method, + AAL: aal, + CompletedAt: time.Now().UTC(), + Provider: providerID, + Organization: organizationID, + }) } func (s *Session) AuthenticatedVia(method identity.CredentialsType) bool { @@ -335,6 +341,9 @@ type AuthenticationMethod struct { // OIDC or SAML provider id used for authentication Provider string `json:"provider,omitempty"` + + // The Organization id used for authentication + Organization string `json:"organization,omitempty"` } // Scan implements the Scanner interface. diff --git a/spec/api.json b/spec/api.json index d163cd2d65f6..fbc0fe874e56 100644 --- a/spec/api.json +++ b/spec/api.json @@ -825,6 +825,9 @@ "metadata_public": { "$ref": "#/components/schemas/nullJsonRawMessage" }, + "organization_id": { + "$ref": "#/components/schemas/NullUUID" + }, "recovery_addresses": { "description": "RecoveryAddresses contains all the addresses that can be used to recover an identity.", "items": { @@ -942,6 +945,9 @@ "initial_refresh_token": { "type": "string" }, + "organization": { + "type": "string" + }, "provider": { "type": "string" }, @@ -1204,6 +1210,9 @@ "oauth2_login_request": { "$ref": "#/components/schemas/OAuth2LoginRequest" }, + "organization_id": { + "$ref": "#/components/schemas/NullUUID" + }, "refresh": { "description": "Refresh stores whether this login flow should enforce re-authentication.", "type": "boolean" @@ -1619,6 +1628,9 @@ "oauth2_login_request": { "$ref": "#/components/schemas/OAuth2LoginRequest" }, + "organization_id": { + "$ref": "#/components/schemas/NullUUID" + }, "request_url": { "description": "RequestURL is the initial URL that was requested from Ory Kratos. It can be used\nto forward information contained in the URL's path or query for example.", "type": "string" @@ -1770,6 +1782,9 @@ "title": "The method used", "type": "string" }, + "organization": { + "type": "string" + }, "provider": { "description": "OIDC or SAML provider id used for authentication", "type": "string" @@ -5096,6 +5111,13 @@ "schema": { "type": "string" } + }, + { + "in": "query", + "name": "organization", + "schema": { + "type": "string" + } } ], "responses": { @@ -5854,6 +5876,13 @@ "schema": { "type": "string" } + }, + { + "in": "query", + "name": "organization", + "schema": { + "type": "string" + } } ], "responses": { diff --git a/spec/swagger.json b/spec/swagger.json index df1b67be4013..176dfb093be2 100755 --- a/spec/swagger.json +++ b/spec/swagger.json @@ -1600,6 +1600,11 @@ "description": "An optional Hydra login challenge. If present, Kratos will cooperate with\nOry Hydra to act as an OAuth2 identity provider.\n\nThe value for this parameter comes from `login_challenge` URL Query parameter sent to your\napplication (e.g. `/login?login_challenge=abcde`).", "name": "login_challenge", "in": "query" + }, + { + "type": "string", + "name": "organization", + "in": "query" } ], "responses": { @@ -2228,6 +2233,11 @@ "description": "The URL to return the browser to after the verification flow was completed.\n\nAfter the registration flow is completed, the user will be sent a verification email.\nUpon completing the verification flow, this URL will be used to override the default\n`selfservice.flows.verification.after.default_redirect_to` value.", "name": "after_verification_return_to", "in": "query" + }, + { + "type": "string", + "name": "organization", + "in": "query" } ], "responses": { @@ -3183,6 +3193,19 @@ } } }, + "NullUUID": { + "description": "NullUUID can be used with the standard sql package to represent a\nUUID value that can be NULL in the database.", + "type": "object", + "properties": { + "UUID": { + "type": "string", + "format": "uuid" + }, + "Valid": { + "type": "boolean" + } + } + }, "OAuth2Client": { "type": "object", "title": "OAuth2Client OAuth 2.0 Clients are used to perform OAuth 2.0 and OpenID Connect flows. Usually, OAuth 2.0 clients are generated for applications which want to consume your OAuth 2.0 or OpenID Connect capabilities.", @@ -3864,6 +3887,9 @@ "metadata_public": { "$ref": "#/definitions/nullJsonRawMessage" }, + "organization_id": { + "$ref": "#/definitions/NullUUID" + }, "recovery_addresses": { "description": "RecoveryAddresses contains all the addresses that can be used to recover an identity.", "type": "array", @@ -3975,6 +4001,9 @@ "initial_refresh_token": { "type": "string" }, + "organization": { + "type": "string" + }, "provider": { "type": "string" }, @@ -4235,6 +4264,9 @@ "oauth2_login_request": { "$ref": "#/definitions/OAuth2LoginRequest" }, + "organization_id": { + "$ref": "#/definitions/NullUUID" + }, "refresh": { "description": "Refresh stores whether this login flow should enforce re-authentication.", "type": "boolean" @@ -4630,6 +4662,9 @@ "oauth2_login_request": { "$ref": "#/definitions/OAuth2LoginRequest" }, + "organization_id": { + "$ref": "#/definitions/NullUUID" + }, "request_url": { "description": "RequestURL is the initial URL that was requested from Ory Kratos. It can be used\nto forward information contained in the URL's path or query for example.", "type": "string" @@ -4757,6 +4792,9 @@ "method": { "$ref": "#/definitions/identityCredentialsType" }, + "organization": { + "type": "string" + }, "provider": { "description": "OIDC or SAML provider id used for authentication", "type": "string"