Data validation rules

Identity Cloud provides at least two ways to validate data before that data is written to a user profile. As the name suggests, field validations are applied to the fields that appear on Identity Cloud screens. If a user uses one of these screens to update their user profile, field validations check the data before that data is submitted. If a field fails validation the form can’t be submitted.

As you might expect, field validations work only on fields: these validations are employed when users submit changes by using an Identity Cloud screen or when administrators update a profile by using the Authentication API. (The Authentication API typically updates data by referencing fields and field names.) However, it’s also possible to update a user profile by using the Entity and Entity Types API or by using Console. Fields aren’t used in either of those cases. Instead, updates target the underlying user profile attributes, bypassing fields altogether. In turn, that means bypassing field validations as well.

Fortunately, you can use data validation rules to set validation requirements on the attribute itself. If you do that it doesn’t matter which tool you employ to change an attribute value: the value you’re trying to assign to the attribute must pass validation before it can be assigned. For example, note what happens if you use Console to try and save a user profile that fails data validation:

A field validation wouldn’t catch this similar error because Console doesn’t rely on fields.

📘

So if data validations work in all situations why would you ever want to use a field validation? Well, the value of a field validation is that the validation takes place before the user submits the form. That means that the user has an opportunity to fix problems before trying to save their changes. By comparison, a data validation runs only when a form is submitted and Identity Cloud tries to write the data to the user profile. If validation fails at that point, you’ll have to create code to trap the error, show the form again, fill in any data that did pass validation, etc. etc. Field validations save you from all that additional effort.

To apply a validation rule to an attribute (or to multiple attributes: the same rule can be assigned to more than one attribute), use the /entityType.addRule operation and the POST method. For example:

curl -L -X POST 'https://se-demos-gstemp.us-dev.janraincapture.com/entityType.addRule' \
  -H 'Authorization: Basic eTR4Zmc2ZjQ0bXNhYzN2ZXBqanZ4Z2d6dnQzZTNzazk6OTVjY3hrN2N6YnZ1eng2ZHB0ZTVrOXA2ZGo1Ynpla3U=' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'type_name=user' \
  --data-urlencode 'definition={"greater-than": 100}' \
  --data-urlencode 'attributes=["sampleAttribute"]' \
  --data-urlencode 'description=Ensures that submitted values are greater than 100.'

In the preceding command:

  • type_name specifies the entity type where the attribute (or attributes) are stored, Each entity type has its own set of validation rules.
  • definition specifies the validation itself. See the next section of this document for more information about the validations available to you.
  • attributes lists the attributes that the rule applies to. This must be configured as a JSON array, with each item in the array an attribute name.
  • description serves as the error message should validation fail. This member is optional, but recommended. (Note that it also makes it easier for you to identify individual rules and what they’re used for.)

So what happens if you set a data validation and then make an API call that fails that validation? In that case, the API call fails and the user profile doesn’t get updated. (At all: any single validation failure causes the entire API call to fail.) In addition, you’ll get back a detailed error message similar to this:

{
  "attribute_name": "/test",
  "code": 360,
  "constraint_name": "validation-constraint",
  "error": "constraint_violation",
  "error_description": "the value provided for /test violates the validation rule 'Ensures that submitted values are greater than 100.'",
  "request_id": "h3qp944nxkdb7q8z",
  "stat": "error"
}

A word of caution

Before creating and assigning validation rules there are at least two things you should be aware of. For one, although you can create validation rules you can’t modify validation rules. For example, suppose you create a validation rule that sets the maximum value of a field to 99. Sometime down the road, however, you realize you need to change this validation: the maximum value should actually be 999. However, there’s no way to edit the existing validation rule and change the maximum value.

And yes, you could create a second validation rule, one that sets the maximum value to 999. However, that means that the attribute now has two validation rules, one that sets the maximum value to 99 and a second that sets the maximum value to 999. Suppose you try to enter the value 698. That value passes the validation that sets the maximum value to 999. That’s the good news. The bad news? The value 698 fails the validation rule that sets the maximum value to 99. As a result, your update fails. You can set a million validation rules on an attribute but if even one of those million rules is triggered then validation fails.

So what do you do if you need to modify a validation rule? Here's one solution: delete the invalid rule and then assign the new rule. That way the attribute won’t have any conflicting rules, and the value 698 validates as expected.

The other thing you should know is related to this. When you create a validation rule, Identity Cloud verifies that the rule is appropriate for the underlying attribute. For example, suppose you try to set the maximum value of the birthday attribute to 99. That makes no sense: birthday is a date attribute, and there’s no such date as 99. As a result, your API call fails with an error similar to this:

{
  "code": 200,
  "error": "invalid_argument",
  "error_description": "can not apply integer validation rule to '/birthday' attribute",
  "request_id": "qruj45bgttqejhyc",
  "stat": "error"
}

But while Identity Cloud checks for conflicts within a rule (like trying to assign an integer validation to a date value) Identity Cloud doesn’t check for conflicts between validation rules. For example, you can create a validation rule that sets the default value of an attribute to 100, another that sets the default value to 200, and a third that sets the default value to 300. So what gets assigned as the default value when you create a new profile? That’s hard to say, but there’s a very good chance it won’t be the default value you actually wanted. If you’re getting unexpected results with your validation rules, use the entityType.rules operation to return all your rules and see if you’ve got multiple, and conflicting, rules applied to a given attribute.


Validations

Validation rules are composed of one or more data validations. The following table lists the validations you can use when creating a validation rule:

ValidationData types
default

Sets a default value for the attribute. Anytime a new user profile is created, the value of the assigned attribute is automatically set to this default (unless, of course, the user provides a different value). For example, suppose you set the default value of the primaryAddress.country attribute to US. A user creates a new user profile, but doesn’t supply a value for their country of residence. In that case, the value of primaryAddress.country is automatically set to US.

Keep in mind that default only applies when a new profile is created. Suppose a user created a profile before you implemented this validation, and that user didn’t supply a value for the primaryAddress.country attribute. When the validation rule is applied that user’s profile won’t be updated: their primaryAddress.country attribute isn’t changed to the new default value. This is true even if the user makes some other change to their profile (for example, updating the name of the organization they work for). Default values apply only at profile creation.

The definition syntax for the default validation looks similar to this:

["default": "US"]
integer
string
greater-than

Verifies that the value entered for the assigned attribute is greater than the specified value. For example, suppose you set greater-than to 100. In that case, a value of 99 fails validation, because 99 is less than 100. Similarly, a value of 101 passes validation. Note that a value of 100 fails validation. That’s because the validation is “greater than” and not “greater than or equal to.”

The definition syntax for the greater-than validation looks similar to this:

{"greater-than": 100}
integer
less-than

Verifies that the value entered for the assigned attribute is less than the specified value. For example, suppose you set less-than to 100. In that case, a value of 101 fails validation, because 101 is greater than 100. Similarly, a value of 99 passes validation. Note that a value of 100 fails validation. That’s because the validation is “less than” and not “less than or equal to.”

The definition syntax for the less-than validation looks similar to this:

{"less-than": 100}
integer
match-all

Typically used to apply regular expression validation to an attribute. For example, suppose your membership IDs consist of all uppercase characters: TGSREFAJK. In that case, you can use match-all and the regular expression [A-Z] to ensure that only uppercase letters appear in the value supplied by the user:

{"match-all":"[A-Z]"}

Needless to say, you can create more complex regular expressions as needed. For example, this regular expression allows the use of uppercase letters, lowercase letters, and the digits 0 through 9:

{"match-all":"[A-Z][a-z][0-9]"}
regular expression
match

Among other things, provides a way for you to limit data entry to a specified set of choices. For example, suppose you pose a question to users and give them three options:

• agree
• disagree
• no opinion

By using the match validation, you can ensure that users are only able to enter one of the three provided options: any other value (even something like I agree) fails validation.

Note. Admittedly, in this simple example it might be better to have users select an allowed value from a dropdown list or a set of radio buttons. See the not operator for a different, and perhaps more practical, use of the match validation.

The definition for the match validation looks similar to this:

{"match": "agree|disagree|no opinion"}

Note that the three allowed values are separated by using vertical bars, and with no blank spaces before or after each option. Here’s another example, this one limiting users to entering one of several US state abbreviations:

"match": "WA|OR|CA|ID|NV|AZ|MT|NM|CO|UT"}
regular expression
max-length

Specifies the maximum number of characters that can be used in a value. For example, suppose you allow users to enter a screen name, but you want to limit the size of those screen names to no more than 12 characters. To do that, set max-length to 12. In that case, Charles passes validation, but His Royal Majesty King Charles III doesn't.

Keep in mind that max-length only sets the maximum number of characters that can be used in the string: it doesn’t impose a minimum number of characters. That’s the job of the min-length validation.

The definition syntax for the max-length validation looks similar to this:

{"max-length": 12}
string
min-age

Enables you to set an age restriction on the assigned attribute. For example, suppose your site is intended for users 21 years old or older. To check a user’s age, you can set the min-age validation to 21. If a user enters a birthdate of 06/03/2012 that entry fails validation: it hasn’t been at least 21 years since June 3, 2012. However, a birthdate of 06/03/2000 passes validation.

We should probably note that minimum age restrictions don’t really verify a user’s age; after all, a user can enter any birthdate they want and Identity Cloud has no way of knowing whether or not that’s the user’s real birthday. But this form of “age-gating” does provide at least some control over who can and who can’t access your site.

The definition syntax for the min-age validation looks similar to this:

{"min-age": 21}
date
min-length

Specifies the minimum number of characters that can be used in a value. For example, suppose you allow users to enter a screen name, but you want those screen names to contain at least 6 characters (no screen names like P or 6 allowed). To do that, set min-length to 6. In that case, Leonard passes validation, but Lee does not.

Keep in mind that min-length only sets the minimum number of characters that can be used in the string: it doesn’t impose a maximum number of characters. That’s the job of the max-length validation.

The definition syntax for the min-length validation looks similar to this:

{"min-length": 6}
string
truncate

Truncates (cuts off) a string after the specified number of characters. For example, suppose you set truncate to 10, and the user enters the value Akamai Identity Cloud. In that case, the value of the assigned attribute is set to Akamai Ide, the first 10 characters in Akamai Identity Cloud. Users can enter string values of practically any length, but only the first x number of characters are written to the user profile.

The definition syntax for the truncate validation looks similar to this:

{"truncate": 200}
string

Operators

In addition to the validations themselves, you also have several operators available to you when creating validation rules. The and and or Boolean operators provide a way for you to string together multiple validations into a single statement. Meanwhile, instead of validating what a value is, the not operator enables you to validate what a validation isn’t. For example, suppose that, for superstitious reasons, you don’t want to allow users to set an attribute value to thirteen. That’s fine. This validation, which uses the not operator, does just that:

{"not": {"match": "thirteen"}}

Here's more information about these operators:


and

The and operator provides a way to specify multiple validations in a single statement. To pass validation, a value must pass each of these validations. For example, suppose you have a string attribute where the values needs to contain at least 5 characters but no more than 10 characters. Here’s a validation that checks for that:

{"and": [{"min-length": 5},{"max-length": 10}]}

To use the and operator start by creating the individual validations. In this case, we use a min-length validation and a max-length validation:

{"min-length": 5}
{"max-length": 10}

Enclose all those validations in a JSON array:

[{"min-length": 5},{"max-length": 10}]

And then use that array as the value for an and key:

{"and": [{"min-length": 5},{"max-length": 10}]}

The net effect? To pass validation a value must have a minimum length of 5 characters and a maximum length of 10 characters: 4 characters fails to meet the minimum length criteria, and 12 characters fails to meet the maximum length criteria.


not

The not operator is typically used to ensure that an attribute isn’t set to a specific value. Many organizations use this validation to prevent users from setting, say, their display name to an obscene or derogatory term, or to a term that, for whatever reason, isn’t appropriate for user display names. For example, suppose you give users a chance to enter their favorite animal, but you don’t want them to enter jackalope, bigfoot, or werewolf.

{"not": {"match": "jackalope|bigfoot|werewolf"}}

As you can see, to use the not operator you first create a typical validation. In this case, that’s a match validation with three options:

{"match": "jackalope|bigfoot|werewolf"}

After that, insert the not operator as your key and use the array as the value:

{"not": {"match": "jackalope|bigfoot|werewolf"}}

In this example, the not operator simply says, “To pass validation, the value must not be one of the following.” That’s all there is to it.


or

With the or operator, you specify multiple validations, just like you do with the and operator. In this case, however, a value can pass validation by meeting any one of those validations. For example, suppose you have a attribute for storing a user’s membership ID. Some of your early adopters have IDs that contain one or two digits: 4, 13, 88. However, most of your users have IDs of 10000 or greater. That means that a valid ID can be less than 100 or it can be greater than 9999. What it can’t be is any number between 100 and 10000. For example, 2399 isn’t a valid ID.

So how can you check to see if a membership ID meets one of those two criteria? Here’s how:

{"or": [{"greater-than": 9999},{"less-than": 100}]}

In this example, we again start with two separate validations:

{"greater-than": 9999}
{"less-than": 100}

We then add both of those validations to a JSON array:

[{"greater-than": 9999},{"less-than": 100}]

Finally, we create a key-value pair using the or operator as the key and the JSON array as the value:

{"or": [{"greater-than": 9999},{"less-than": 100}]}

To pass validation, a membership ID needs to either be less than 100 or greater than 9999.