mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 22:57:31 +00:00

<!-- Please inform yourself about the contribution guidelines on submitting a PR here: https://github.com/zitadel/zitadel/blob/main/CONTRIBUTING.md#submit-a-pull-request-pr. Take note of how PR/commit titles should be written and replace the template texts in the sections below. Don't remove any of the sections. It is important that the commit history clearly shows what is changed and why. Important: By submitting a contribution you agree to the terms from our Licensing Policy as described here: https://github.com/zitadel/zitadel/blob/main/LICENSING.md#community-contributions. --> # Which Problems Are Solved Okta sends a random password in the request to create a user during SCIM provisioning, irrespective of whether the `Sync Password` option is enabled or disabled on Okta, and this password does not comply with the default password complexity set in Zitadel. This PR adds a workaround to create users without issues in such cases. # How the Problems Are Solved - A new metadata configuration called `urn:zitadel:scim:ignorePasswordOnCreate` is added to the Machine User that is used for provisioning - During SCIM user creation requests, if the `urn:zitadel:scim:ignorePasswordOnCreate` is set to `true` in the Machine User's metadata, the password set in the create request is ignored # Additional Changes # Additional Context The random password is ignored (if set in the metadata) only during customer creation. This change does not affect SCIM password updates. - Closes #10009 --------- Co-authored-by: Marco A. <marco@zitadel.com>
104 lines
3.1 KiB
Go
104 lines
3.1 KiB
Go
package metadata
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"github.com/zitadel/zitadel/internal/query"
|
|
)
|
|
|
|
type Key string
|
|
type ScopedKey string
|
|
|
|
const (
|
|
externalIdProvisioningDomainPlaceholder = "{provisioningDomain}"
|
|
|
|
KeyPrefix = "urn:zitadel:scim:"
|
|
KeyProvisioningDomain Key = KeyPrefix + "provisioningDomain"
|
|
KeyIgnorePasswordOnCreate Key = KeyPrefix + "ignorePasswordOnCreate"
|
|
|
|
KeyExternalId Key = KeyPrefix + "externalId"
|
|
keyScopedExternalIdTemplate = KeyPrefix + externalIdProvisioningDomainPlaceholder + ":externalId"
|
|
KeyMiddleName Key = KeyPrefix + "name.middleName"
|
|
KeyHonorificPrefix Key = KeyPrefix + "name.honorificPrefix"
|
|
KeyHonorificSuffix Key = KeyPrefix + "name.honorificSuffix"
|
|
KeyProfileUrl Key = KeyPrefix + "profileUrl"
|
|
KeyTitle Key = KeyPrefix + "title"
|
|
KeyLocale Key = KeyPrefix + "locale"
|
|
KeyTimezone Key = KeyPrefix + "timezone"
|
|
KeyIms Key = KeyPrefix + "ims"
|
|
KeyPhotos Key = KeyPrefix + "photos"
|
|
KeyAddresses Key = KeyPrefix + "addresses"
|
|
KeyEntitlements Key = KeyPrefix + "entitlements"
|
|
KeyRoles Key = KeyPrefix + "roles"
|
|
KeyEmails Key = KeyPrefix + "emails"
|
|
)
|
|
|
|
var (
|
|
ScimUserRelevantMetadataKeys = []Key{
|
|
KeyExternalId,
|
|
KeyMiddleName,
|
|
KeyHonorificPrefix,
|
|
KeyHonorificSuffix,
|
|
KeyProfileUrl,
|
|
KeyTitle,
|
|
KeyLocale,
|
|
KeyTimezone,
|
|
KeyIms,
|
|
KeyPhotos,
|
|
KeyAddresses,
|
|
KeyEntitlements,
|
|
KeyRoles,
|
|
KeyEmails,
|
|
}
|
|
|
|
AttributePathToMetadataKeys = map[string][]Key{
|
|
"externalid": {KeyExternalId},
|
|
"name": {KeyMiddleName, KeyHonorificPrefix, KeyHonorificSuffix},
|
|
"name.middlename": {KeyMiddleName},
|
|
"name.honorificprefix": {KeyHonorificPrefix},
|
|
"name.honorificsuffix": {KeyHonorificSuffix},
|
|
"profileurl": {KeyProfileUrl},
|
|
"title": {KeyTitle},
|
|
"locale": {KeyLocale},
|
|
"timezone": {KeyTimezone},
|
|
"ims": {KeyIms},
|
|
"photos": {KeyPhotos},
|
|
"addresses": {KeyAddresses},
|
|
"entitlements": {KeyEntitlements},
|
|
"roles": {KeyRoles},
|
|
"emails": {KeyEmails},
|
|
}
|
|
)
|
|
|
|
func ScopeExternalIdKey(provisioningDomain string) ScopedKey {
|
|
return ScopedKey(strings.Replace(keyScopedExternalIdTemplate, externalIdProvisioningDomainPlaceholder, provisioningDomain, 1))
|
|
}
|
|
|
|
func ScopeKey(ctx context.Context, key Key) ScopedKey {
|
|
// only the externalID is scoped
|
|
if key == KeyExternalId {
|
|
return GetScimContextData(ctx).ExternalIDScopedMetadataKey
|
|
}
|
|
|
|
return ScopedKey(key)
|
|
}
|
|
|
|
func MapToScopedKeyMap(md map[string][]byte) map[ScopedKey][]byte {
|
|
result := make(map[ScopedKey][]byte, len(md))
|
|
for k, v := range md {
|
|
result[ScopedKey(k)] = v
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func MapListToScopedKeyMap(metadataList []*query.UserMetadata) map[ScopedKey][]byte {
|
|
metadataMap := make(map[ScopedKey][]byte, len(metadataList))
|
|
for _, entry := range metadataList {
|
|
metadataMap[ScopedKey(entry.Key)] = entry.Value
|
|
}
|
|
|
|
return metadataMap
|
|
}
|