"org.keycloak.storage.UserStorageProvider": [
  {
  "name": "{{ KEYCLOAK_LDAP_CMP_NAME }}",
  "providerId": "ldap",
  "subComponents": {
    "org.keycloak.storage.ldap.mappers.LDAPStorageMapper": [
    
      {# ---------------------- First Name ---------------------- #}
      {
        "name": "first name",
        "providerId": "user-attribute-ldap-mapper",
        "subComponents": {},
        "config": {
          "ldap.attribute": [ "{{ LDAP.USER.ATTRIBUTES.FIRSTNAME }}" ],
          "attribute.force.default": [ "true" ],
          "is.mandatory.in.ldap": [ "true" ],
          "is.binary.attribute": [ "false" ],
          "always.read.value.from.ldap": [ "true" ],
          "read.only": [ "false" ],
          "user.model.attribute": [ "firstName" ]
        }
      },

      {# ---------------------- Last Name ----------------------- #}
      {
        "name": "last name",
        "providerId": "user-attribute-ldap-mapper",
        "subComponents": {},
        "config": {
          "ldap.attribute": [ "{{ LDAP.USER.ATTRIBUTES.SURNAME }}" ],
          "is.mandatory.in.ldap": [ "true" ],
          "always.read.value.from.ldap": [ "true" ],
          "read.only": [ "false" ],
          "user.model.attribute": [ "lastName" ]
        }
      },

      {# ---------------------- Full Name (cn) ------------------ #}
      {
        "name": "full name",
        "providerId": "full-name-ldap-mapper",
        "subComponents": {},
        "config": {
          "read.only": [ "false" ],
          "write.only": [ "true" ],
          "ldap.full.name.attribute": [ "{{ LDAP.USER.ATTRIBUTES.FULLNAME }}" ]
        }
      },

      {# ---------------------- Username ------------------------ #}
      {
        "name": "username",
        "providerId": "user-attribute-ldap-mapper",
        "subComponents": {},
        "config": {
          "ldap.attribute": [ "{{ LDAP.USER.ATTRIBUTES.ID }}" ],
          "is.mandatory.in.ldap": [ "true" ],
          "attribute.force.default": [ "false" ],
          "is.binary.attribute": [ "false" ],
          "always.read.value.from.ldap": [ "false" ],
          "read.only": [ "false" ],
          "user.model.attribute": [ "username" ]
        }
      },

      {# ---------------------- Email --------------------------- #}
      {
        "name": "email",
        "providerId": "user-attribute-ldap-mapper",
        "subComponents": {},
        "config": {
          "ldap.attribute": [ "{{ LDAP.USER.ATTRIBUTES.MAIL }}" ],
          "is.mandatory.in.ldap": [ "false" ],
          "read.only": [ "false" ],
          "always.read.value.from.ldap": [ "false" ],
          "user.model.attribute": [ "email" ]
        }
      },

      {# ---------------------- SSH Public Key ------------------ #}
      {
        "name": "SSH Public Key",
        "providerId": "user-attribute-ldap-mapper",
        "subComponents": {},
        "config": {
          "ldap.attribute": [ "{{ LDAP.USER.ATTRIBUTES.SSH_PUBLIC_KEY }}" ],
          "is.mandatory.in.ldap": [ "false" ],
          "attribute.force.default": [ "false" ],
          "is.binary.attribute": [ "false" ],
          "read.only": [ "false" ],
          "always.read.value.from.ldap": [ "true" ],
          "user.model.attribute": [ "{{ LDAP.USER.ATTRIBUTES.SSH_PUBLIC_KEY }}" ]
        }
      },

      {# ---------------------- Nextcloud Quota ----------------- #}
      {
        "name": "{{ LDAP.USER.ATTRIBUTES.NEXTCLOUD_QUOTA }}",
        "providerId": "user-attribute-ldap-mapper",
        "subComponents": {},
        "config": {
          "ldap.attribute": [ "{{ LDAP.USER.ATTRIBUTES.NEXTCLOUD_QUOTA }}" ],
          "is.mandatory.in.ldap": [ "false" ],
          "attribute.force.default": [ "false" ],
          "is.binary.attribute": [ "false" ],
          "always.read.value.from.ldap": [ "false" ],
          "read.only": [ "false" ],
          "user.model.attribute": [ "{{ LDAP.USER.ATTRIBUTES.NEXTCLOUD_QUOTA }}" ]
        }
      },

      {# ---------------------- Creation Date ------------------- #}
      {
        "name": "creation date",
        "providerId": "user-attribute-ldap-mapper",
        "subComponents": {},
        "config": {
          "ldap.attribute": [ "createTimestamp" ],
          "is.mandatory.in.ldap": [ "false" ],
          "always.read.value.from.ldap": [ "true" ],
          "read.only": [ "true" ],
          "user.model.attribute": [ "createTimestamp" ]
        }
      },

      {# ---------------------- Modify Date --------------------- #}
      {
        "name": "modify date",
        "providerId": "user-attribute-ldap-mapper",
        "subComponents": {},
        "config": {
          "ldap.attribute": [ "modifyTimestamp" ],
          "is.mandatory.in.ldap": [ "false" ],
          "always.read.value.from.ldap": [ "true" ],
          "read.only": [ "true" ],
          "user.model.attribute": [ "modifyTimestamp" ]
        }
      },

      {# ---------------------- LDAP Groups -> KC Groups -------- #}
      {
        "name": "ldap-roles",
        "providerId": "group-ldap-mapper",
        "subComponents": {},
        "config": {
          "membership.attribute.type": [ "DN" ],
          "group.name.ldap.attribute": [ "cn" ],
          "membership.user.ldap.attribute": [ "{{ LDAP.USER.ATTRIBUTES.ID }}" ],
          "preserve.group.inheritance": [ "true" ],
          "groups.dn": [ "{{ LDAP.DN.OU.ROLES }}" ],
          "mode": [ "LDAP_ONLY" ],
          "user.roles.retrieve.strategy": [ "LOAD_GROUPS_BY_MEMBER_ATTRIBUTE" ],
          "groups.ldap.filter": ["{{ LDAP.RBAC.FLAVORS | ldap_groups_filter }}"],
          "membership.ldap.attribute": [ "member" ],
          "ignore.missing.groups": [ "true" ],
          "group.object.classes": [ "groupOfNames" ],
          "memberof.ldap.attribute": [ "memberOf" ],
          "drop.non.existing.groups.during.sync": [ "false" ],
          "groups.path": [ "{{ KEYCLOAK_RBAC_GROUP_NAME }}" ]
        }
      },
      {
        "name": "phone number",
        "providerId": "user-attribute-ldap-mapper",
        "subComponents": {},
        "config": {
          "ldap.attribute": [ "telephoneNumber" ],
          "is.mandatory.in.ldap": [ "false" ],
          "always.read.value.from.ldap": [ "true" ],
          "read.only": [ "false" ],
          "user.model.attribute": [ "phoneNumber" ]
        }
      },
      {
        "name": "locale",
        "providerId": "user-attribute-ldap-mapper",
        "subComponents": {},
        "config": {
          "ldap.attribute": [ "preferredLanguage" ],
          "is.mandatory.in.ldap": [ "false" ],
          "always.read.value.from.ldap": [ "true" ],
          "read.only": [ "false" ],
          "user.model.attribute": [ "locale" ]
        }
      },
      {
        "name": "uidNumber",
        "providerId": "user-attribute-ldap-mapper",
        "subComponents": {},
        "config": {
          "ldap.attribute": [ "uidNumber" ],
          "is.mandatory.in.ldap": [ "false" ],
          "always.read.value.from.ldap": [ "true" ],
          "read.only": [ "false" ],
          "user.model.attribute": [ "uidNumber" ]
        }
      }
      {% if keycloak_map_ldap_realm_roles | default(false) %},
      {# ---------------------- LDAP -> Realm Roles (optional) -- #}
      {
        "name": "ldap-realm-roles",
        "providerId": "role-ldap-mapper",
        "subComponents": {},
        "config": {
          "mode": [ "LDAP_ONLY" ],
          "membership.attribute.type": [ "DN" ],
          "user.roles.retrieve.strategy": [ "LOAD_ROLES_BY_MEMBER_ATTRIBUTE" ],
          "roles.dn": [ "{{ LDAP.DN.OU.ROLES }}" ],
          "membership.ldap.attribute": [ "member" ],
          "membership.user.ldap.attribute": [ "{{ LDAP.USER.ATTRIBUTES.ID }}" ],
          "memberof.ldap.attribute": [ "memberOf" ],
          "role.name.ldap.attribute": [ "cn" ],
          "use.realm.roles.mapping": [ "true" ],
          "role.object.classes": [ "groupOfNames" ]
        }
      }{% endif %}
    ]
  },
  "config": {
    "fullSyncPeriod": [ "-1" ],
    "pagination": [ "true" ],
    "connectionTrace": [ "false" ],
    "startTls": [ "false" ],
    "usersDn": [ "{{ LDAP.DN.OU.USERS }}" ],
    "connectionPooling": [ "true" ],
    "cachePolicy": [ "DEFAULT" ],
    "useKerberosForPasswordAuthentication": [ "false" ],
    "importEnabled": [ "true" ],
    "enabled": [ "true" ],
    "bindCredential": [ "{{ KEYCLOAK_LDAP_BIND_PW }}" ],
    "changedSyncPeriod": [ "-1" ],
    "usernameLDAPAttribute": [ "{{ LDAP.USER.ATTRIBUTES.ID }}" ],
    "bindDn": [ "{{ KEYCLOAK_LDAP_BIND_DN }}" ],
    "vendor": [ "other" ],
    "uuidLDAPAttribute": [ "{{ LDAP.USER.ATTRIBUTES.ID }}" ],
    "allowKerberosAuthentication": [ "false" ],
    "connectionUrl": [ "{{ KEYCLOAK_LDAP_URL }}" ],
    "syncRegistrations": [ "true" ],
    "authType": [ "simple" ],
    "krbPrincipalAttribute": [ "krb5PrincipalName" ],
    "searchScope": [ "1" ],
    "useTruststoreSpi": [ "always" ],
    "usePasswordModifyExtendedOp": [ "true" ],
    "trustEmail": [ "false" ],

    {# Build objectClasses from structural + auxiliary definitions #}
    "userObjectClasses": [
      {{ KEYCLOAK_LDAP_USER_OBJECT_CLASSES | trim | to_json }}
    ],

    "rdnLDAPAttribute": [ "{{ LDAP.USER.ATTRIBUTES.ID }}" ],
    "editMode": [ "WRITABLE" ],
    "validatePasswordPolicy": [ "false" ],

    {# Recommended: prune Keycloak shadow users not in LDAP anymore #}
    "removeInvalidUsersEnabled": [ "true" ]
  }
}
]