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.

  • Group type

  • Property value

  • Global distribution group

  • 2

  • Domain local distribution group

  • 4

  • Universal distribution group

  • 8

  • Global security group

  • -2147483644

  • Domain local security group

  • -2147483646

  • Universal security group

  • -2147483640

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.

  • Group type

  • Property value

  • Microsoft 365 group

  • 1

  • Distribution group

  • 2

  • Mail-enabled security group

  • 3

  • Security group

  • 4

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.

See also