Expressions
The expression syntax IdRa supports, a subset of the Okta Expression Language.
IdRa evaluates a safe subset of the Okta Expression Language. The engine is in place for group rules, attribute mappings, SAML and token claims, and policies, which adopt it feature by feature. Those screens don't accept expressions yet.
References
| Syntax | Meaning |
|---|---|
user.firstName | An attribute of the person |
appuser.login | The person's attribute in the current app |
app.domain, org.subDomain | App and organization properties |
idpuser.email | The person at the identity provider |
session.amr, access.scope | Session and token properties |
user.address.city, user.tags[0] | Nested attributes and array elements. The index must be a whole number |
Each feature decides which of these it provides. A missing attribute is null, while an unknown namespace such as usr.email is an error.
Values and operators
| Kind | Examples |
|---|---|
| Literals | 'text', "text", 1234, 3.141, true, null, {1, 2, 3} |
| Concatenation | user.firstName + " " + user.lastName (null becomes empty text; two numbers add) |
| Comparison | ==, !=, <, >, <=, >= |
| Boolean | AND, OR, ! (also &&, ||) |
| Ternary | user.salary > 100 ? 'Senior' : 'Junior' |
| Elvis | user.nickname ?: user.firstName uses the right side when the left is null or empty |
Comparisons are strict and case-sensitive: "123" == 123 is false, and Convert.toNum converts text first. <, >, <= and >= compare two numbers or two strings, are false if either side is null, and are an error otherwise.
Conditions need a boolean. null counts as false, so !user.isContractor is true for a person without that attribute. To require the attribute, write user.isContractor == false.
Functions
| Group | Functions |
|---|---|
String | append, join, len, removeSpaces, replace, replaceFirst, startsWith, endsWith, stringContains, stringSwitch, substring, substringBefore, substringAfter, toUpperCase, toLowerCase |
Arrays | add, remove, clear, get, flatten, contains, size, isEmpty, toCsvString |
Convert | toInt, toNum |
Time | now(), the current UTC time in ISO 8601 |
| Groups | isMemberOfGroupName, isMemberOfGroup, isMemberOfAnyGroup, isMemberOfGroupNameStartsWith, isMemberOfGroupNameContains, with or without a user. prefix |
toLowerCase, toUpperCase, substring, substringBefore and substringAfter also work without the String. prefix.
String.replaceandString.replaceFirstmatch literal text, not patterns.String.stringSwitch(input, default, key, value, ...)returns the value of the first key thatinputcontains.Arraysfunctions also acceptnull(an empty array) and comma-separated text.Arrays.containsandArrays.removecompare single values as text, soArrays.contains("10, 20", 10)is true.
Examples:
String.toLowerCase(String.substringBefore(user.email, "@"))
isMemberOfGroupName("Admins") OR Arrays.contains(user.tags, "oncall")
String.stringSwitch(user.department, "Other", "Eng", "Engineering", "Sales", "Revenue")Not supported
These are rejected with a clear error:
- Regular expressions:
matchesandisMemberOfGroupNameRegex. Time.nowwith a time zone or format, and the otherTimefunctions.Iso3166Convert,getFilteredGroups,user.getGroups,user.getInternalProperty, and the manager, assistant and linked-object functions.- Methods on values (
user.email.toLowerCase()), maps and projections (.![name]). Use the function form:String.toLowerCase(user.email).
Limits
An expression can be up to 4096 characters and nested up to 32 levels. A text result can be up to 65,536 characters; going over is an error when the expression runs. Internal names such as __proto__, constructor and prototype are rejected.