Setting property values
When you send a request to create or modify a directory object via REST API, the following properties have to be set in a specific way.
Account options {id=account-options}
The Account options flags are set by modifying the userAccountControl property. Each flag has a corresponding integer value, and these values are cumulative. For a complete list of flags and their integer representations, see the ADS_USER_FLAG_ENUM enumerator. Here are some of the frequently used combinations:
Account options | Value | Details |
---|---|---|
Disabled account | 2 | - |
Disabled account Must change password at next logon |
-2147483646 | -2147483648 + 2 |
Disabled account Password never expires |
65538 | 2 + 65536 |
Cannot change password | 64 | - |
Password never expires | 65536 | - |
User cannot change password Password never expires |
65600 | 64 + 65536 |
User cannot change password Password never expires Smart card required |
327744 | 64 + 65536 + 262144 |
Must change password at next logon | -2147483648 | - |
Smart card required Must change password at next logon |
-2147221504 | -2147483648 + 262144 |
Examples
Set the account options to Cannot change password and Password never expires:
{
"propertyName": "userAccountControl",
"propertyType": "Integer",
"values": [ 65600 ]
}
To change specific flags of an existing account without changing other flags, you need add the mask attribute to the request body.
See details {id=mask-account-options}
A mask lets you isolate and change specific flags while preserving the state of other flags. The mask should contain the combination of flags to change, expressed in decimal. For example, to change only the Disabled account (2) flag and the Password never expires (65536) flag, use 65538 (2+65536) as your mask.
How the flags will be changed – depends on the supplied value. The supplied value should contain the combination of flags to set, expressed in decimal. Flags included in the mask but not in the value will be cleared. For example, using a mask of 65538 (2+65536) and a value of 2:
- The Disabled account (2) flag will be set
- The Password never expires (65536) flag will be cleared
Whenever you set the Must change password at next logon flag, you must clear Password never expires and User cannot change password flags.
Whenever you set the Password never expires or the User cannot change password flag, you must clear the Must change password at next logon flag.
Examples
Set the Disabled account flag and clear the Password never expires flag:
{
"propertyName": "userAccountControl",
"propertyType": "Integer",
"values": [ 2 ],
"mask": 65538
}
Set the Disabled account flag:
{
"propertyName": "userAccountControl",
"propertyType": "Integer",
"values": [ 2 ],
"mask": 2
}
Clear the Disabled account flag:
{
"propertyName": "userAccountControl",
"propertyType": "Integer",
"values": [ 0 ],
"mask": 2
}
Set the User cannot change password and Disabled account flags; clear the Must change password at next logon flag:
{
"propertyName": "userAccountControl",
"propertyType": "Integer",
"values": [ 66 ],
"mask": -2147483582
}
Clear the User cannot change password and Disabled account flags:
{
"propertyName": "userAccountControl",
"propertyType": "Integer",
"values": [ 0 ],
"mask": 66
}
Group type {id=group-type}
Active Directory groups
The group type and scope is set by modifying the groupType property. Specify the required combination of group scope and group type as the property value. For a list of group types/scopes and their integer representations, see the ADS_GROUP_TYPE_ENUM enumerator.
Examples
Make the group a Universal distribution group:
{
"propertyName": "groupType",
"propertyType": "Integer",
"values": [ 8 ]
}
To change the group type or scope independently of each other, you need add the mask attribute to the request body.
See details {id=mask-group-type}
A mask represents a combination of property flags to change, expressed in decimal. The groupType property has one flag responsible for the group type – Security (2147483648), and three mutually exclusive flags responsible for the group scope – Global/Local/Universal (2, 4, and 8 respectively). Therefore:
- To change the group type, use -2147483648 as your mask.
- To change the group scope, use 14 (2+4+8) as your mask.
The new group type/scope is determined by the value you supply:
Operation | Value | Mask |
---|---|---|
Change the group scope to Universal | 8 | 14 |
Change the group scope to Domain local | 4 | 14 |
Change the group scope to Global | 2 | 14 |
Change the group type to Distribution | 0 | -2147483648 |
Change the group type to Security | -2147483648 | -2147483648 |
Examples
Change the group type to Distribution:
{
"propertyName": "groupType",
"propertyType": "Integer",
"values": [ 0 ],
"mask": -2147483648
}
Change the group scope to Global:
{
"propertyName": "groupType",
"propertyType": "Integer",
"values": [ 2 ],
"mask": 14
}
Microsoft Entra groups
The group type for Microsoft Entra groups is determined during creation and can't be changed afterwards. The group type is set by modifying the adm-AzureGroupType property. Here are all the possible values.
Example
Make the group a Mail-enabled security group:
{
"propertyName": "adm-AzureGroupType",
"propertyType": "Integer",
"values": [ 3 ]
}
Logon hours {id=logon-hours}
Logon hours are represented as an array of 21 bytes, with 3 bytes per day and 1 bit per hour. The first bit in the array is Sunday, 00:00 to 0:59 in the UTC time zone, the second bit is Sunday, 01:00 to 01:59, and so on. A bit set to 1 means logon during this hour is allowed, and 0 means logon is not allowed.
The following code sample creates the logon hours value, where logon is allowed on Monday (9am-5pm) and Tuesday (11am-3pm):
class LogonDay {
[DayOfWeek]$DayOfWeek
[Int]$StartHour
[Int]$NumHours
}
# Allow logon during specific hours on Monday and Tuesday
[LogonDay[]]$allowedLogon = @(
[LogonDay]@{DayOfWeek="Monday"; StartHour=9; NumHours=8} # Monday 9AM - 5PM
[LogonDay]@{DayOfWeek="Tuesday"; StartHour=11; NumHours=4} # Tuesday 11AM - 3PM
)
# Create an empty byte array and populate it with the specified logon hours in the local time zone
[Byte[]]$logonHours = @(0) * 21
$timeZoneOffset = -[System.TimeZoneInfo]::Local.BaseUtcOffset.Hours
foreach ($day in $allowedLogon)
{
$endHour = $day.StartHour + $day.NumHours
for ($hour = $day.StartHour; $hour -lt $endHour; $hour++)
{
$byteIndex = (($hour - ($hour % 8)) / 8) + $day.DayOfWeek * 3 # 3 bytes per day
$bitIndex = (($hour % 8) + $byteIndex * 8)
$totalBitCount = 168 # 21 byte * 8 bits in byte
$bitIndex = ((($bitIndex + $timeZoneOffset) % $totalBitCount) + $totalBitCount) % $totalBitCount
$byteIndex = [System.Math]::Floor([Decimal]($bitIndex / 8))
$bitInByteIndex = $bitIndex % 8
$logonHours[$byteIndex] = $logonHours[$byteIndex] -bor [Byte](1 -shl $bitInByteIndex)
}
}
To set logon hours, convert the resulting byte array into a Base64-encoded string:
$value = [Convert]::ToBase64String($logonHours)
Specify this Base-64 encoded string in the corresponding element of the request body:
{
"propertyName": "logonHours",
"propertyType": "Binary",
"values": [ "AAAAAMA/AAAPAAAAAAAAAAAAAAAA" ]
}
Timestamp (Account expires, adm-CustomAttributeTimestamp1, etc.) {id=account-expires}
Values for timestamp properties (e.g. Account expires, Password last set, adm-CustomAttributeTimestamp1) can be specified in the following way:
- "Never"
- "Unspecified"
- Specific date
- Never
-
{ "propertyName": "accountExpires", "propertyType": "Timestamp", "values": [ "Never" ] }
- Unspecified
-
{ "propertyName": "accountExpires", "propertyType": "Timestamp", "values": [ "Unspecified" ] }
- Date
-
{ "propertyName": "accountExpires", "propertyType": "Timestamp", "values": [ "2020-10-22T06:00:00Z" ] }
It is recommended to specify the date in the ISO 8601 format:
- 2020-10-22T06:00:00+03:00
However, many other formats will also be accepted, for example:
- 2020-10-22 06:00 +3
- 06.00 22/10/2020 +3:00
- 6AM 22.10.2020 +3
Always specify the time zone when setting a date. Otherwise, Adaxes service will assume time component is in the time zone of the computer where Adaxes service is running.