IDaaS has a built-in expression engine that lets you transform user attributes before passing them to applications or identity providers. Use expressions in SAML and OpenID Connect (OIDC) applications to add or modify parameters in the returned user information—for example, to concatenate fields, evaluate conditions, or reformat values. You can also use expressions when configuring field mappings for identity provider (IdP) synchronization.
For more information, see SAML attribute statement mapping rules, OIDC id_token extension value mapping rules, and Manage account fields.
An expression consists of two parts:
Models — data sources, including User (IDaaS accounts) and AppUser (application accounts)
Functions — operations applied to model field values
Models
User
The User model represents IDaaS accounts. Reference fields using user.<fieldId>, for example user.username or user.lockExpireTime.
| Field display name | Field ID | Data type | Required | Unique | User permissions | Description |
|---|---|---|---|---|---|---|
| Account ID | userId | String | No | Yes | Visible | The user ID. |
| Username | username | String | Yes | Yes | Visible | The username. |
| Display name | displayName | String | No | No | Editable | The user's display name. |
| String | No | Yes | Editable | The email address. | ||
| Mobile phone | phoneNumber | Number | No | Yes | Editable | The phone number. |
| Phone area code | phoneRegion | Number | No | No | Editable | The area code. For China, the value is 86 (without 00 or +). |
| External ID | userExternalId | String | No | Yes | Visible | The user's external ID. |
| Source type | userSourceType | String | No | No | Visible | Valid values: build_in (self-built), ding_talk (DingTalk), ad (AD), ldap (LDAP), we_com (WeCom), lark (Lark), idp_auto_build (automatically created by an IdP). |
| Source ID | userSourceId | String | No | No | Visible | The source ID. |
| Account status | status | String | No | No | Visible | Valid values: enabled, disabled. |
| Description | description | String | No | No | Visible | The description. |
| Account expiration time | accountExpireTime | Number | No | No | Visible | UNIX timestamp in milliseconds. |
| Account registration time | registerTime | Number | No | No | Visible | UNIX timestamp in milliseconds. |
| Password expiration time | passwordExpireTime | Number | No | No | Visible | UNIX timestamp in milliseconds. |
| Lock expiration time | lockExpireTime | Number | No | No | Visible | UNIX timestamp in milliseconds. |
| Creation time | createTime | Number | No | No | Visible | UNIX timestamp in milliseconds. |
| Update time | updateTime | Number | No | No | Visible | UNIX timestamp in milliseconds. |
User model JSON example
{
"userId": "user_x3zyd6cxxxxxxxxxxxxx",
"username": "name_001",
"displayName": "displayname_001",
"passwordSet": true,
"phoneRegion": "86",
"phoneNumber": "333xxxx3333",
"phoneNumberVerified": true,
"email": "xxxxx@example.com",
"emailVerified": true,
"userExternalId": "b2ed5fc0xxxxxxxxxx",
"userSourceType": "ding_talk",
"userSourceId": "corp_1234xxxxxxx",
"status": "enabled",
"accountExpireTime": "-1",
"passwordExpireTime": "-1",
"registerTime": "1730454581598",
"lockExpireTime": "-1",
"createTime": "1730454582379",
"updateTime": "1733479455307",
"customFieldMap": {
"place": { "fieldName": "place", "fieldValue": "beijing" },
"age": { "fieldName": "age", "fieldValue": "18" }
},
"customFields": [
{ "fieldName": "place", "fieldValue": "beijing" },
{ "fieldName": "age", "fieldValue": "18" }
],
"identityProviderUserMap": {
"idp_m2gngriuenktdkxxxxxx": {
"identityProviderId": "idp_m2gngriuenktdkxxxxxx",
"identityProviderType": "ding_talk",
"identityProviderExternalId": "corp_1234xxxxxxx",
"identityProviderUserId": "b2ed5fc0xxxxx"
}
},
"organizationalUnits": [
{ "organizationalUnitId": "ou_sdfadtaaxxxxxx", "organizationalUnitName": "name_001", "primary": false },
{ "organizationalUnitId": "ou_werttxxxxxx", "organizationalUnitName": "name_002", "primary": true }
],
"primaryOrganizationalUnitId": "ou_werttxxxxxx",
"groups": [
{ "groupId": "group_jp6al4sn4n4wjgjxxxxxx", "groupName": "group1", "groupExternalId": "group_jp6al4sn4n4wjgjxxxxxx" },
{ "groupId": "group_vavikcxewkf5h3oxxxxxx", "groupName": "group2", "groupExternalId": "group_vavikcxewkf5h3oxxxxxx" }
]
}AppUser
The AppUser model represents application accounts. Reference fields using appUser.<property>, for example appUser.username.
| Property | Description |
|---|---|
| username | The username of the application account. |
IdP User
The IdP User model is used for field mappings when synchronizing with an identity provider. For example, the DingTalk office location field is idpUser.work_place. For available fields, see the documentation for your identity provider, such as the DingTalk Help Document - User Details.
For OIDC identity providers (see Attach an OIDC identity provider), when using expressions in the automatic attachment feature, the idpUser. prefix applies only to the sub, phoneNumber, and email fields from the id_token (for example, idpUser.sub). For all other fields, use the idpUser.rawUserInfo. prefix (for example, idpUser.rawUserInfo.aud).
Functions
Functions operate on model field values and are grouped by category below.
String functions
| Function | Signature | Return type | Description | Example |
|---|---|---|---|---|
| Append | Append(str1, str2, ..., strN) | String | Concatenates parameters into a new string. Equivalent to str1 + str2 + .... | Append("str1", "@example.com") → str1@example.com |
| Join | Join(source1, source2, ..., sourceN, separator) | String | Joins multiple source values into a single string using the specified separator. | Join("str1", "str2", 123, "-") → str1-str2-123 |
| StringReplace | StringReplace(source, target, replacement) | String | Performs a simple string replacement of target in source with replacement. | StringReplace("hello $str", "$str", "world") → hello world |
| Trim | Trim(source) | String | Removes leading and trailing whitespace. | Trim(" 123 ") → 123 |
| TrimLeft | TrimLeft(source) | String | Removes leading whitespace only. | TrimLeft(" 123 ") → 123 |
| TrimRight | TrimRight(source) | String | Removes trailing whitespace only. | TrimRight(" 123 ") → 123 |
| ToLower | ToLower(source) | String | Converts to all lowercase. | ToLower(" Abc ") → abc |
| ToUpper | ToUpper(source) | String | Converts to all uppercase. | ToUpper(" Abc ") → ABC |
| Substring | Substring(source, fromIndex, endIndex) | String | null | Returns the substring from fromIndex (inclusive) to endIndex (exclusive). If fromIndex is negative, it is treated as 0. Returns null if either index is not an integer. | Substring("0123456", 1, 5) → 1234; Substring("0123456", -1, 7) → 0123456; Substring("0123456", "1", 5) → null |
| SubstringBefore | SubstringBefore(source, subString) | String | null | Returns the portion of source before the first occurrence of subString. Returns null if subString is not found. | SubstringBefore("test@example@com", "@") → test |
| Split | Split(source, separator) | Array | Splits a string into an array of substrings using the specified separator. | Split("str1,str2,str3", ",") → Array(str1, str2, str3) |
| Contains | Contains(str1, str2) | Boolean | Returns true if str1 contains str2, false otherwise. | Contains("test", "t") → true; Contains("test", "a") → false |
| StartsWith | StartsWith(str1, str2) | Boolean | Returns true if str1 starts with str2. Takes exactly two parameters. | StartsWith("test", "t") → true; StartsWith("test", "e") → false |
| Equals | Equals(str1, str2[, ignoreCase]) | Boolean | Compares two strings for equality. Pass true as the third parameter for case-insensitive comparison, or false for case-sensitive (the default). | Equals("test", "Test") → false; Equals("test", "Test", true) → true |
Condition functions
| Function | Signature | Return type | Description | Example |
|---|---|---|---|---|
| IIF | IIF(condition, whenTrue, whenFalse) | Any | Returns whenTrue if condition is true, otherwise returns whenFalse. | IIF(true, 1, 2) → 1; IIF(false, 1, 2) → 2 |
| IsNull | IsNull(value) | Boolean | Returns true if value is null or missing. Returns false for empty strings. | IsNull(null) → true; IsNull("") → false |
| IsNullOrEmpty | IsNullOrEmpty(value) | Boolean | Returns true if value is null or an empty string. | IsNullOrEmpty(user.email) → true if email is null or missing; IsNullOrEmpty("") → true |
| Coalesce | Coalesce(source1, source2, ..., sourceN, defaultValue) | Any | null | Returns the first non-empty parameter. A non-empty value is not null and has a length greater than 0. Returns null if all parameters are empty. | Coalesce("", user.phoneRegion, "86") → 86 if the phone area code is empty or missing |
| Or | Or(condition1, condition2, ..., conditionN) | Boolean | Returns true if any condition is true. | Or(true, false) → true; Or(false, false) → false |
| And | And(condition1, condition2, ..., conditionN) | Boolean | Returns true only if all conditions are true. | And(true, false) → false; And(true, true, true) → true |
| xOr | xOr(condition1, condition2) | Boolean | Takes exactly two conditions. Returns true if exactly one condition is true, false if both are the same. | xOr(true, false) → true; xOr(true, true) → false; xOr(false, false) → false |
Array functions
| Function | Signature | Return type | Description | Example |
|---|---|---|---|---|
| Array | Array(source1, source2, ...) | Array | Combines values into an array. Values can be of the Object type. | Array(1, 2, 3) → [1, 2, 3] |
| ArrayAdd | ArrayAdd(array, element) | Array | Adds an element to an array. | ArrayAdd(Array(), "test") → ["test"] |
| ArrayMap | ArrayMap($ArrayObject, __item.ObjectProperty) | Array | Creates a new array by extracting a specific property from each object in an array. | ArrayMap(user.groups, __item.groupId) → ["groupId1","groupId2","groupId3"] |
| ArrayIndex | ArrayIndex(array, n) | Any | Returns the element at index n. Index starts from 0. | ArrayIndex(Array(1, 2, 3), 0) → 1 |
| ArrayJoin | ArrayJoin(array, separator) | String | Joins array elements into a string using the specified separator. | ArrayJoin(Array(1, 2, 3), "-") → 1-2-3 |
Object functions
| Function | Signature | Return type | Description | Example |
|---|---|---|---|---|
| Object | Object(key1, value1, key2, value2, ...) | Object | Creates an object from key-value pairs. Supports zero or an even number of parameters. | Object("key1", "value1", "key2", "value2") → {"key1": "value1", "key2": "value2"} |
| ObjectIndex | ObjectIndex(object, "propertyName") | Any | Returns the value of the specified property. ObjectIndex(user, "username") is equivalent to user.username. | — |
| ObjectToJsonString | ObjectToJsonString(object) | String | Converts an object to a JSON string. | ObjectToJsonString(user.groups) → JSON string representation |
Time functions
| Function | Signature | Return type | Description | Example |
|---|---|---|---|---|
| Now | Now() | String | Returns the current UTC date and time in yyyy-MM-dd'T'HH:mm:ssXXX format. | Output: 2021-11-01T09:52:11Z |
| CurrentTimeMillis | CurrentTimeMillis() | Number | Returns the current UNIX timestamp in milliseconds. | — |
Phone number functions
Both ExtractPhoneRegion and ExtractPhoneNumber use ISO 3166 Alpha-2 country codes (for example, CN, US, TW). See the ISO 3166 Country Codes standard for the full list.
The parameters work as follows depending on the format of the source phone number:
Number already has a `+` prefix (for example,
+86131xxxxx000): pass onlysource. The function extracts the area code from the prefix.Number has an area code but no `+` prefix (for example,
86131xxxxx000): passsource,defaultRegion, and setautoAppendPlusSignaltotrue.Number has no area code (for example,
131xxxxx000): passsource,defaultRegion, and setautoAppendPlusSignaltofalse.
| Function | Signature | Return type | Description |
|---|---|---|---|
| ExtractPhoneRegion | ExtractPhoneRegion(source[, defaultRegion, autoAppendPlusSignal]) | String | Extracts the area code from a phone number. |
| ExtractPhoneNumber | ExtractPhoneNumber(source[, defaultRegion, autoAppendPlusSignal]) | String | Extracts the phone number without the area code. |
ExtractPhoneRegion examples
| Phone number format | Expression | Return value |
|---|---|---|
+86131xxxxx000, +86 131xxxxx000, or +86-131xxxxx000 | ExtractPhoneRegion(idpUser.mobile) | 86 |
86131xxxxx000, 86 131xxxxx000, or 86-131xxxxx000 | ExtractPhoneRegion(idpUser.mobile, "CN", true) | 86 |
131xxxxx000 | ExtractPhoneRegion(idpUser.mobile, "CN", false) | 86 |
ExtractPhoneNumber examples
| Phone number format | Expression | Return value |
|---|---|---|
+86131xxxxx000, +86 131xxxxx000, or +86-131xxxxx000 | ExtractPhoneNumber(idpUser.mobile) | 131xxxxx000 |
86131xxxxx000, 86 131xxxxx000, or 86-131xxxxx000 | ExtractPhoneNumber(idpUser.mobile, "CN", true) | 131xxxxx000 |
131xxxxx000 | ExtractPhoneNumber(idpUser.mobile, "CN", false) | 131xxxxx000 |
SAML-specific functions
| Function | Signature | Return type | Description | Example |
|---|---|---|---|---|
| SamlArray | SamlArray(Array()) | SAML attribute | Available only for SAML SSO. Formats an array as a SAML attribute with multiple AttributeValue elements. | SamlArray(Array("group1","group2")) → SAML response with separate <saml2:AttributeValue> elements for group1 and group2 |
Common expressions
The following examples use the sample user data below. Copy and adapt these expressions directly.
Sample user data:
user.username:name_001user.displayName:displayname_001user.email:xxxxx@example.comuser.phoneRegion:86user.phoneNumber:333xxxx3333user.groups: two groups with IDsgroup_jp6al4sn4n4wjgjxxxxxxandgroup_vavikcxewkf5h3oxxxxxx
| Goal | Expression | Output |
|---|---|---|
| Append a domain to the username | Append(user.username, "@example.com") | name_001@example.com |
| Return email if set, otherwise fall back to phone number | Coalesce(user.email, user.phoneNumber) | xxxxx@example.com |
| Use a default phone number when the field is empty | IIF(IsNullOrEmpty(user.phoneNumber), "1888888****", user.phoneNumber) | 333xxxx3333 |
| Concatenate the area code and phone number with a hyphen | Join(user.phoneRegion, user.phoneNumber, "-") | 86-333xxxx3333 |
| Build a welcome message with the display name | StringReplace("hello $DisplayName", "$DisplayName", user.displayName) | hello displayname_001 |
| Mask the middle four digits of the phone number | Append(SubString(user.phoneNumber, 0, 4), "****", SubString(user.phoneNumber, 8, 10)) | 333x****33 |
| Extract the username from an email address | SubstringBefore(user.email, "@") | xxxxx |
| Format the email field as a SCIM-compatible array | Array(Object("email", user.email, "type", "work", "primary", true)) | [{"email":"xxxxx@example.com","type":"work","primary":true}] |
| Get a list of group IDs for a user | ArrayMap(user.groups, __item.groupId) | ["group_jp6al4sn4n4wjgjxxxxxx","group_vavikcxewkf5h3oxxxxxx"] |