Files
zitadel/backend/v3/domain/settings.go
T
jmaretteandGitHub f34cc45eac feat(oidc): add RFC 7591 dynamic client registration (#12313)
# Which Problems Are Solved

ZITADEL cannot currently be used as an OAuth 2.0 Authorization Server by
clients that need to register themselves at runtime:

- There is no [OAuth 2.0 Dynamic Client Registration (RFC
7591)](https://datatracker.ietf.org/doc/html/rfc7591) endpoint, and no
`registration_endpoint` is advertised in the discovery document.
- This blocks [Model Context Protocol
(MCP)](https://modelcontextprotocol.io) clients (Claude Desktop,
claude.ai, Cursor, the MCP SDKs), whose OAuth 2.1 authorization profile
expects an Authorization Server that supports dynamic client
registration. They self-register before any user context exists and only
then start the authorization code + PKCE flow.

# How the Problems Are Solved

## Control plane: instance security settings

No feature flag and no runtime config. A
`DynamicClientRegistrationSettings` message is nested under the instance
`SecuritySettings` in `settings/v2`, next to `embedded_iframe` and
`enable_impersonation`:

| `enabled` | `allow_unauthenticated` | Behaviour |
| --- | --- | --- |
| `false` (default) | — | `POST /oauth/v2/register` returns `404`,
`registration_endpoint` absent from discovery |
| `true` | `false` (default) | Token-gated registration, client homed in
the token's organization |
| `true` | `true` | Open registration for MCP hosts, client homed in the
instance default organization |

Both values are carried on `authz.Instance` and loaded with the
instance, exactly like `EnableImpersonation`, so the discovery document
and the endpoint read them per request without an extra query.
`allow_unauthenticated` implies `enabled` in both implementations, so a
single setting closes the endpoint.

Adding the two columns bumps the projection table to
`projections.security_policies3`, following what the impersonation
setting did for `security_policies2`.

## Authorization: a dedicated permission, not `project.app.write`

- New org-scoped permission **`project.app.register_dynamic`**, granted
by default to `ORG_OWNER`, `IAM_OWNER` and `IAM_ORG_MANAGER` — in both
`InternalAuthZ` and `SystemAuthZ`, mirroring where `project.app.write`
already lives.
- New built-in role **`ORG_DYNAMIC_CLIENT_REGISTRAR`** carrying only
that permission, so a service user can self-register clients without
gaining write access to the organization's existing applications.
- Open mode (`allow_unauthenticated = true`) requires no token and no
permission: that is the MCP self-register path.
- A valid token whose user lacks the permission is answered with **`403
insufficient_scope`** (RFC 6750 §3.1) rather than `401 invalid_token`,
so a caller can tell "your token is bad" from "your token may not do
this". `verifyAccessToken` also reports invalid tokens as permission
denied, so the authorization failure is marked explicitly to keep the
two apart.

The check runs once, at the endpoint, right after the token is verified
and before any state is created, so it also gates the auto-provisioning
of the organization's DCR project. The permission itself lives in the
command layer next to the others
(`Commands.CheckPermissionRegisterDynamicClient`). As the OIDC endpoints
are not behind the authorization interceptor, the caller identity is
derived from the verified token, the way token exchange does for the
impersonating actor.

## Registration itself

- **Registered clients are ordinary OIDC applications.** The endpoint
reuses the existing application-creation events
(`NewApplicationAddedEvent` and `NewOIDCConfigAddedEvent`), so the whole
token, authorization and introspection flow keeps working unchanged.
They are stored in a dedicated, auto-provisioned project named `ZITADEL
DCR` per organization (name lookup), so they do not pollute the
`IAMProject` or other projects.
- Input is validated with the existing `GetOIDCV1Compliance` rules;
`private_key_jwt` and `jwks`/`jwks_uri` are rejected with
`invalid_client_metadata`.
- **Endpoint wiring without forking the library.** `NewServer` calls
`op.RegisterServer` instead of `op.RegisterLegacyServer`, so the new
route can be added through the same `op.WithSetRouter` hook as the
authorize callback. `op.RegisterLegacyServer` appends a middleware after
the caller options, which chi forbids once a route has been registered;
`op.NewIssuerInterceptor` reproduces the issuer middleware it would
otherwise add. The `/oauth/v2` routing prefix is unchanged.

# Additional Changes

- **`application_type` inference for custom-scheme redirects** (last
commit, isolated). `application_type` is an OpenID Connect member; RFC
7591 does not define it, so clients that only implement RFC 7591 omit
it. Native MCP hosts doing so register custom-scheme redirect URIs,
which ZITADEL reserves for native applications, and the OIDC default of
`web` rejected them with `invalid_redirect_uri`. Inference is limited to
custom schemes and to an absent `application_type`, so every request
accepted today keeps its current application type and auth method — an
`http` loopback redirect still yields a web application. Happy to drop
this commit if you would rather keep it out of this PR.
- **Docs**: a Dynamic Client Registration integration guide, a
`registration_endpoint` section on the OpenID Connect endpoints page,
and the new role in the administrators table (plus its description in
the Console translations).

# Additional Context

- Part of #9810. This is **Phase 1 (DCR)**; #12315 adds RFC 7592 and
#12316 adds CIMD, both stacked on this branch and rebased once this
lands.
- Implements the control-plane and authorization model requested in the
review of this PR, itself a refinement of the direction in
https://github.com/zitadel/zitadel/issues/9810#issuecomment-4891176997.
- **Out of scope (deliberately)**: RFC 7592, CIMD, persisting free-form
metadata (`logo_uri`, `contacts`, and similar), and `private_key_jwt` /
`jwks_uri` (rejected cleanly). No new event types.
- Follow-ups explicitly left out, per the review: DCR client lifecycle
and richer audit, consent and custom scopes, JWT / `aud` (RFC 8707), and
RFC 8414 AS metadata (currently absent from both ZITADEL and
`zitadel/oidc`).
2026-07-30 14:43:47 +00:00

539 lines
20 KiB
Go

package domain
import (
"context"
"net/url"
"time"
"github.com/zitadel/zitadel/backend/v3/storage/database"
db_json "github.com/zitadel/zitadel/backend/v3/storage/database/json"
)
//go:generate enumer -type SettingType -transform snake -trimprefix SettingType -sql
type SettingType uint8
const (
SettingTypeLogin SettingType = iota
SettingTypeBranding
SettingTypePasswordComplexity
SettingTypePasswordExpiry
SettingTypeDomain
SettingTypeLockout
SettingTypeSecurity
SettingTypeOrganization
SettingTypeNotification
SettingTypeLegalAndSupport
SettingTypeSecretGenerator
)
//go:generate enumer -type SettingState -transform snake -trimprefix SettingState -sql
type SettingState int32
const (
SettingStateActive SettingState = iota
SettingStatePreview
)
type Settings struct {
ID string `json:"id,omitempty" db:"id"`
InstanceID string `json:"instanceId,omitempty" db:"instance_id"`
OrganizationID *string `json:"organizationId,omitempty" db:"organization_id"`
Type SettingType `json:"type,omitempty" db:"type"`
State SettingState `json:"state,omitempty" db:"state"`
Settings []byte `json:"settings,omitempty" db:"settings"`
CreatedAt time.Time `json:"createdAt,omitzero" db:"created_at"`
UpdatedAt time.Time `json:"updatedAt,omitzero" db:"updated_at"`
}
type settingsColumns interface {
IDColumn() database.Column
InstanceIDColumn() database.Column
OrganizationIDColumn() database.Column
TypeColumn() database.Column
StateColumn() database.Column
SettingsColumn() database.Column
CreatedAtColumn() database.Column
UpdatedAtColumn() database.Column
PrimaryKeyColumns() []database.Column
UniqueColumns() []database.Column
}
type settingsConditions interface {
InstanceIDCondition(id string) database.Condition
OrganizationIDCondition(id *string) database.Condition
IDCondition(id string) database.Condition
PrimaryKeyCondition(instanceID, id string) database.Condition
UniqueCondition(instanceID string, orgID *string, typ SettingType, state SettingState) database.Condition
TypeCondition(typ SettingType) database.Condition
}
type settingsChanges interface {
// SetSettings(settings string) database.Change
SetUpdatedAt(updatedAt *time.Time) database.Change
}
type settingsRepository[T any] interface {
settingsColumns
settingsConditions
settingsChanges
Get(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*T, error)
List(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) ([]*T, error)
Set(ctx context.Context, client database.QueryExecutor, settings *T) error
Delete(ctx context.Context, client database.QueryExecutor, condition database.Condition) (int64, error)
}
type PasswordlessType int32
const (
PasswordlessTypeNotAllowed PasswordlessType = iota
PasswordlessTypeAllowed
)
type MultiFactorType int32
const (
MultiFactorTypeUnspecified MultiFactorType = iota
MultiFactorTypeU2FWithPIN
)
type SecondFactorType int32
const (
SecondFactorTypeUnspecified SecondFactorType = iota
SecondFactorTypeTOTP
SecondFactorTypeU2F
SecondFactorTypeOTPEmail
SecondFactorTypeOTPSMS
)
type loginSettingsJSONChanges interface {
SetSettingFields(value LoginSettingsAttributes) database.Change
SetAllowUserNamePassword(value bool) db_json.JsonUpdate
SetAllowRegister(value bool) db_json.JsonUpdate
SetAllowExternalIDP(value bool) db_json.JsonUpdate
SetForceMFA(value bool) db_json.JsonUpdate
SetForceMFALocalOnly(value bool) db_json.JsonUpdate
SetHidePasswordReset(value bool) db_json.JsonUpdate
SetIgnoreUnknownUsernames(value bool) db_json.JsonUpdate
SetAllowDomainDiscovery(value bool) db_json.JsonUpdate
SetDisableLoginWithEmail(value bool) db_json.JsonUpdate
SetDisableLoginWithPhone(value bool) db_json.JsonUpdate
SetPasswordlessType(value PasswordlessType) db_json.JsonUpdate
SetDefaultRedirectURI(value string) db_json.JsonUpdate
SetPasswordCheckLifetime(value time.Duration) db_json.JsonUpdate
SetExternalLoginCheckLifetime(value time.Duration) db_json.JsonUpdate
SetMFAInitSkipLifetime(value time.Duration) db_json.JsonUpdate
SetSecondFactorCheckLifetime(value time.Duration) db_json.JsonUpdate
SetMultiFactorCheckLifetime(value time.Duration) db_json.JsonUpdate
AddMFAType(value MultiFactorType) database.Change
RemoveMFAType(value MultiFactorType) database.Change
AddSecondFactorTypes(value SecondFactorType) database.Change
RemoveSecondFactorTypes(value SecondFactorType) database.Change
}
type LoginSettings struct {
Settings
LoginSettingsAttributes
}
type LoginSettingsAttributes struct {
AllowUserNamePassword *bool `json:"allowUsernamePassword,omitempty"`
AllowRegister *bool `json:"allowRegister,omitempty"`
AllowExternalIDP *bool `json:"allowExternalIdp,omitempty"`
ForceMFA *bool `json:"forceMfa,omitempty"`
ForceMFALocalOnly *bool `json:"forceMfaLocalOnly,omitempty"`
HidePasswordReset *bool `json:"hidePasswordReset,omitempty"`
IgnoreUnknownUsernames *bool `json:"ignoreUnknownUsernames,omitempty"`
AllowDomainDiscovery *bool `json:"allowDomainDiscovery,omitempty"`
DisableLoginWithEmail *bool `json:"disableLoginWithEmail,omitempty"`
DisableLoginWithPhone *bool `json:"disableLoginWithPhone,omitempty"`
PasswordlessType *PasswordlessType `json:"passwordlessType,omitempty"`
DefaultRedirectURI *string `json:"defaultRedirectUri,omitempty"`
PasswordCheckLifetime *time.Duration `json:"passwordCheckLifetime,omitempty"`
ExternalLoginCheckLifetime *time.Duration `json:"externalLoginCheckLifetime,omitempty"`
MFAInitSkipLifetime *time.Duration `json:"mfaInitSkipLifetime,omitempty"`
SecondFactorCheckLifetime *time.Duration `json:"secondFactorCheckLifetime,omitempty"`
MultiFactorCheckLifetime *time.Duration `json:"multiFactorCheckLifetime,omitempty"`
MFAType []MultiFactorType `json:"mfaType,omitempty"`
SecondFactorTypes []SecondFactorType `json:"secondFactors,omitempty"`
}
//go:generate mockgen -typed -package domainmock -destination ./mock/login_settings.mock.go . LoginSettingsRepository
type LoginSettingsRepository interface {
settingsRepository[LoginSettings]
loginSettingsJSONChanges
SetColumns(ctx context.Context, client database.QueryExecutor, settings *Settings, changes ...database.Change) error
}
type BrandingPolicyThemeMode int32
const (
BrandingPolicyThemeAuto BrandingPolicyThemeMode = iota
BrandingPolicyThemeLight
BrandingPolicyThemeDark
)
type brandingSettingsJSONChanges interface {
SetSettingFields(value BrandingSettingsAttributes) database.Change
SetPrimaryColorLight(value string) db_json.JsonUpdate
SetBackgroundColorLight(value string) db_json.JsonUpdate
SetWarnColorLight(value string) db_json.JsonUpdate
SetFontColorLight(value string) db_json.JsonUpdate
SetLogoURLLight(value url.URL) db_json.JsonUpdate
SetIconURLLight(value url.URL) db_json.JsonUpdate
SetPrimaryColorDark(value string) db_json.JsonUpdate
SetBackgroundColorDark(value string) db_json.JsonUpdate
SetWarnColorDark(value string) db_json.JsonUpdate
SetFontColorDark(value string) db_json.JsonUpdate
SetLogoURLDark(value url.URL) db_json.JsonUpdate
SetIconURLDark(value url.URL) db_json.JsonUpdate
SetHideLoginNameSuffix(value bool) db_json.JsonUpdate
SetErrorMsgPopup(value bool) db_json.JsonUpdate
SetDisableWatermark(value bool) db_json.JsonUpdate
SetThemeMode(value BrandingPolicyThemeMode) db_json.JsonUpdate
SetFontURL(value url.URL) db_json.JsonUpdate
}
type BrandingSettings struct {
Settings
BrandingSettingsAttributes
}
type BrandingSettingsAttributes struct {
PrimaryColorLight *string `json:"primaryColorLight,omitempty"`
BackgroundColorLight *string `json:"backgroundColorLight,omitempty"`
WarnColorLight *string `json:"warnColorLight,omitempty"`
FontColorLight *string `json:"fontColorLight,omitempty"`
LogoURLLight *url.URL `json:"logoUrlLight,omitempty"`
IconURLLight *url.URL `json:"iconUrlLight,omitempty"`
PrimaryColorDark *string `json:"primaryColorDark,omitempty"`
BackgroundColorDark *string `json:"backgroundColorDark,omitempty"`
WarnColorDark *string `json:"warnColorDark,omitempty"`
FontColorDark *string `json:"fontColorDark,omitempty"`
LogoURLDark *url.URL `json:"logoUrlDark,omitempty"`
IconURLDark *url.URL `json:"iconUrlDark,omitempty"`
HideLoginNameSuffix *bool `json:"hideLoginNameSuffix,omitempty"`
ErrorMsgPopup *bool `json:"errorMsgPopup,omitempty"`
DisableWatermark *bool `json:"disableMsgPopup,omitempty"`
ThemeMode *BrandingPolicyThemeMode `json:"themeMode,omitempty"`
FontURL *url.URL `json:"fontUrl,omitempty"`
}
//go:generate mockgen -typed -package domainmock -destination ./mock/branding_settings.mock.go . BrandingSettingsRepository
type BrandingSettingsRepository interface {
settingsRepository[BrandingSettings]
brandingSettingsJSONChanges
StateCondition(typ SettingState) database.Condition
Activate(ctx context.Context, client database.QueryExecutor, condition database.Condition) (int64, error)
ActivateAt(ctx context.Context, client database.QueryExecutor, condition database.Condition, updatedAt time.Time) (int64, error)
SetColumns(ctx context.Context, client database.QueryExecutor, settings *Settings, changes ...database.Change) error
}
type passwordComplexitySettingsJSONChanges interface {
SetSettingFields(value PasswordComplexitySettingsAttributes) database.Change
SetMinLength(value uint64) db_json.JsonUpdate
SetHasLowercase(value bool) db_json.JsonUpdate
SetHasUppercase(value bool) db_json.JsonUpdate
SetHasNumber(value bool) db_json.JsonUpdate
SetHasSymbol(value bool) db_json.JsonUpdate
}
type PasswordComplexitySettings struct {
Settings
PasswordComplexitySettingsAttributes
}
type PasswordComplexitySettingsAttributes struct {
MinLength *uint64 `json:"minLength,omitempty"`
HasLowercase *bool `json:"hasLowercase,omitempty"`
HasUppercase *bool `json:"hasUppercase,omitempty"`
HasNumber *bool `json:"hasNumber,omitempty"`
HasSymbol *bool `json:"hasSymbol,omitempty"`
}
//go:generate mockgen -typed -package domainmock -destination ./mock/password_complexity_settings.mock.go . PasswordComplexitySettingsRepository
type PasswordComplexitySettingsRepository interface {
settingsRepository[PasswordComplexitySettings]
passwordComplexitySettingsJSONChanges
}
type passwordExpirySettingsJSONChanges interface {
SetSettingFields(value PasswordExpirySettingsAttributes) database.Change
SetExpireWarnDays(value uint64) db_json.JsonUpdate
SetMaxAgeDays(value uint64) db_json.JsonUpdate
}
type PasswordExpirySettings struct {
Settings
PasswordExpirySettingsAttributes
}
type PasswordExpirySettingsAttributes struct {
ExpireWarnDays *uint64 `json:"expireWarnDays,omitempty"`
MaxAgeDays *uint64 `json:"maxAgeDays,omitempty"`
}
//go:generate mockgen -typed -package domainmock -destination ./mock/password_expiry_settings.mock.go . PasswordExpirySettingsRepository
type PasswordExpirySettingsRepository interface {
settingsRepository[PasswordExpirySettings]
passwordExpirySettingsJSONChanges
}
type lockoutSettingsJSONChanges interface {
SetSettingFields(value LockoutSettingsAttributes) database.Change
SetMaxPasswordAttempts(value uint64) db_json.JsonUpdate
SetMaxOTPAttempts(value uint64) db_json.JsonUpdate
SetShowLockOutFailures(value bool) db_json.JsonUpdate
}
type LockoutSettings struct {
Settings
LockoutSettingsAttributes
}
type LockoutSettingsAttributes struct {
MaxPasswordAttempts *uint64 `json:"maxPasswordAttempts,omitempty"`
MaxOTPAttempts *uint64 `json:"maxOtpAttempts,omitempty"`
ShowLockOutFailures *bool `json:"showLockOutFailures,omitempty"`
}
//go:generate mockgen -typed -package domainmock -destination ./mock/lockout_settings.mock.go . LockoutSettingsRepository
type LockoutSettingsRepository interface {
settingsRepository[LockoutSettings]
lockoutSettingsJSONChanges
}
type securitySettingsJSONChanges interface {
SetSettingFields(value SecuritySettingsAttributes) database.Change
SetEnableIframeEmbedding(value bool) db_json.JsonUpdate
SetAllowedOrigins(values []string) db_json.JsonUpdate
SetEnableImpersonation(value bool) db_json.JsonUpdate
SetEnableDynamicClientRegistration(value bool) db_json.JsonUpdate
SetAllowUnauthenticatedDynamicClientRegistration(value bool) db_json.JsonUpdate
}
type SecuritySettings struct {
Settings
SecuritySettingsAttributes
}
type SecuritySettingsAttributes struct {
EnableIframeEmbedding *bool `json:"enableIframeEmbedding,omitempty"`
AllowedOrigins []string `json:"allowedOrigins,omitempty"`
EnableImpersonation *bool `json:"enableImpersonation,omitempty"`
EnableDynamicClientRegistration *bool `json:"enableDynamicClientRegistration,omitempty"`
AllowUnauthenticatedDynamicClientRegistration *bool `json:"allowUnauthenticatedDynamicClientRegistration,omitempty"`
}
//go:generate mockgen -typed -package domainmock -destination ./mock/security_settings.mock.go . SecuritySettingsRepository
type SecuritySettingsRepository interface {
settingsRepository[SecuritySettings]
securitySettingsJSONChanges
}
type domainSettingsJSONChanges interface {
SetSettingFields(value DomainSettingsAttributes) database.Change
SetLoginNameIncludesDomain(value bool) db_json.JsonUpdate
SetRequireOrgDomainVerification(value bool) db_json.JsonUpdate
SetSMTPSenderAddressMatchesInstanceDomain(value bool) db_json.JsonUpdate
}
type DomainSettings struct {
Settings
DomainSettingsAttributes
}
type DomainSettingsAttributes struct {
LoginNameIncludesDomain *bool `json:"loginNameIncludesDomain,omitempty"`
RequireOrgDomainVerification *bool `json:"requireOrgDomainVerification,omitempty"`
SMTPSenderAddressMatchesInstanceDomain *bool `json:"smtpSenderAddressMatchesInstanceDomain,omitempty"`
}
//go:generate mockgen -typed -package domainmock -destination ./mock/domain_settings.mock.go . DomainSettingsRepository
type DomainSettingsRepository interface {
settingsRepository[DomainSettings]
domainSettingsJSONChanges
}
type organizationSettingsJSONChanges interface {
SetSettingFields(value OrganizationSettingsAttributes) database.Change
SetOrganizationScopedUsernames(value bool) db_json.JsonUpdate
}
type OrganizationSettings struct {
Settings
OrganizationSettingsAttributes
}
type OrganizationSettingsAttributes struct {
OrganizationScopedUsernames *bool `json:"organizationScopedUsernames,omitempty"`
}
//go:generate mockgen -typed -package domainmock -destination ./mock/organization_settings.mock.go . OrganizationSettingsRepository
type OrganizationSettingsRepository interface {
settingsRepository[OrganizationSettings]
organizationSettingsJSONChanges
}
type notificationSettingsJSONChanges interface {
SetSettingFields(value NotificationSettingsAttributes) database.Change
SetPasswordChange(value bool) db_json.JsonUpdate
}
type NotificationSettings struct {
Settings
NotificationSettingsAttributes
}
type NotificationSettingsAttributes struct {
PasswordChange *bool `json:"passwordChange,omitempty"`
}
//go:generate mockgen -typed -package domainmock -destination ./mock/notification_settings.mock.go . NotificationSettingsRepository
type NotificationSettingsRepository interface {
settingsRepository[NotificationSettings]
notificationSettingsJSONChanges
}
type legalAndSupportSettingsJSONChanges interface {
SetSettingFields(value LegalAndSupportSettingsAttributes) database.Change
SetTOSLink(value string) db_json.JsonUpdate
SetPrivacyPolicyLink(value string) db_json.JsonUpdate
SetHelpLink(value string) db_json.JsonUpdate
SetSupportEmail(value string) db_json.JsonUpdate
SetDocsLink(value string) db_json.JsonUpdate
SetCustomLink(value string) db_json.JsonUpdate
SetCustomLinkText(value string) db_json.JsonUpdate
}
type LegalAndSupportSettings struct {
Settings
LegalAndSupportSettingsAttributes
}
type LegalAndSupportSettingsAttributes struct {
TOSLink *string `json:"tosLink,omitempty"`
PrivacyPolicyLink *string `json:"privacyPolicyLink,omitempty"`
HelpLink *string `json:"helpLink,omitempty"`
SupportEmail *string `json:"supportEmail,omitempty"`
DocsLink *string `json:"docsLink,omitempty"`
CustomLink *string `json:"customLink,omitempty"`
CustomLinkText *string `json:"customLinkText,omitempty"`
}
//go:generate mockgen -typed -package domainmock -destination ./mock/legal_and_support_settings.mock.go . LegalAndSupportSettingsRepository
type LegalAndSupportSettingsRepository interface {
settingsRepository[LegalAndSupportSettings]
legalAndSupportSettingsJSONChanges
}
type SecretGeneratorSettings struct {
Settings
SecretGeneratorSettingsAttributes
}
//go:generate mockgen -typed -package domainmock -destination ./mock/secret_generator_settings.mock.go . SecretGeneratorSettingsRepository
type SecretGeneratorSettingsRepository interface {
settingsRepository[SecretGeneratorSettings]
secretGeneratorSettingsJSONChanges
}
type secretGeneratorSettingsJSONChanges interface {
SetSettingFields(value SecretGeneratorSettingsAttributes) database.Change
SetClientSecret(value ClientSecretAttributes) db_json.JsonUpdate
SetInitializeUserCode(value InitializeUserCodeAttributes) db_json.JsonUpdate
SetEmailVerificationCode(value EmailVerificationCodeAttributes) db_json.JsonUpdate
SetPhoneVerificationCode(value PhoneVerificationCodeAttributes) db_json.JsonUpdate
SetPasswordVerificationCode(value PasswordVerificationCodeAttributes) db_json.JsonUpdate
SetPasswordlessInitCode(value PasswordlessInitCodeAttributes) db_json.JsonUpdate
SetDomainVerification(value DomainVerificationAttributes) db_json.JsonUpdate
SetOTPSMS(value OTPSMSAttributes) db_json.JsonUpdate
SetOTPEmail(value OTPEmailAttributes) db_json.JsonUpdate
}
type SecretGeneratorSettingsAttributes struct {
ClientSecret *ClientSecretAttributes `json:"clientSecret,omitempty"`
InitializeUserCode *InitializeUserCodeAttributes `json:"initializeUserCode,omitempty"`
EmailVerificationCode *EmailVerificationCodeAttributes `json:"emailVerificationCode,omitempty"`
PhoneVerificationCode *PhoneVerificationCodeAttributes `json:"phoneVerificationCode,omitempty"`
PasswordVerificationCode *PasswordVerificationCodeAttributes `json:"passwordVerificationCode,omitempty"`
PasswordlessInitCode *PasswordlessInitCodeAttributes `json:"passwordlessInitCode,omitempty"`
DomainVerification *DomainVerificationAttributes `json:"domainVerification,omitempty"`
OTPSMS *OTPSMSAttributes `json:"otpSms,omitempty"`
OTPEmail *OTPEmailAttributes `json:"otpEmail,omitempty"`
InviteCode *InviteCodeAttributes `json:"inviteCode,omitempty"`
}
type ClientSecretAttributes struct {
SecretGeneratorAttrs
}
type InitializeUserCodeAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type EmailVerificationCodeAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type PhoneVerificationCodeAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type PasswordVerificationCodeAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type PasswordlessInitCodeAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type DomainVerificationAttributes struct {
SecretGeneratorAttrs
}
type OTPSMSAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type OTPEmailAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type InviteCodeAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type SecretGeneratorAttrs struct {
Length *uint `json:"length,omitempty"`
IncludeLowerLetters *bool `json:"includeLowerLetters,omitempty"`
IncludeUpperLetters *bool `json:"includeUpperLetters,omitempty"`
IncludeDigits *bool `json:"includeDigits,omitempty"`
IncludeSymbols *bool `json:"includeSymbols,omitempty"`
}
type SecretGeneratorAttrsWithExpiry struct {
Expiry *time.Duration `json:"expiry,omitempty"`
SecretGeneratorAttrs
}