Script repository

Self-service temporary group membership

Updated on: Jan 18, 2026, Views: 5800

Group membership

To enable users to add themselves to AD groups for a specific period of time:

  1. Create a custom command that executes Script 1. The script adds the user who executes the command to the group it is executed on.
  2. Create a scheduled task that runs Script 2. It will remove users from groups when their temporary membership expires. The task must be configured for the Group object type.

Script 1: Add temporary membership

To execute the script, create a custom command configured for the Group object type. The script adds the user who executes the command to the group it is executed on. Also, it adds a record specifying when to remove the user from the group.

Parameters

  • $memberListProperty - the name of the attribute that stores information on temporary group members.
  • $durationInHours - the duration of temporary membership (in hours).
$memberListProperty = "adm-CustomAttributeTextMultiValue1" # TODO: modify me
$durationInHours = 24 # TODO: modify me

# Build initiator path.
$guid = [Guid]$Context.Initiator.UserAdsObject.Get("ObjectGuid")
$initiatorPath = "Adaxes://<GUID=$guid>"

# Build initiator record.
$endDate = [System.Datetime]::UtcNow.AddHours($durationInHours)
$initiatorRecord = "$initiatorPath " + $endDate.ToFileTimeUtc()

# Get group records.
try
{
    $records = $Context.TargetObject.GetEx($memberListProperty)
}
catch
{
    $records = @()
}

# Check whether initiator has already requested access to the group.
$addNewRecord = $True
for ($i = 0; $i -lt $records.Length; $i++)
{
    $path = ($records[$i] | Select-String -Pattern "Adaxes\:\/\/\<GUID=.+\>").Matches[0].Value
    if ($path -ne $initiatorPath)
    {
        continue
    }
    
    # The initiator has already requested access to this group, update date.
    $records[$i] = $initiatorRecord
    $addNewRecord = $False
    break
}

if ($addNewRecord)
{
    # Add information when to remove the initiator from the group.
    $records += $initiatorRecord
    
    # Add initiator to the group.
    $Context.TargetObject.Add($Context.Initiator.UserAdsObject.AdsPath)
}

# Update the list of members to remove.
$Context.TargetObject.PutEx("ADS_PROPERTY_UPDATE", $memberListProperty, $records)
$Context.TargetObject.SetInfo()

Script 2: Remove temporary members

The script removes users from groups when their temporary membership expires. To execute the script, create a scheduled task configured for the Group object type.

In the script, the $memberListProperty variable specifies the name of the attribute that stores information on temporary members. It must be the same as $memberListProperty in Script 1.

$memberListProperty = "adm-CustomAttributeTextMultiValue1" # TODO: modify me

# Get members to remove.
try
{
    $records = $Context.TargetObject.GetEx($memberListProperty)
}
catch
{
    return
}

$currentDate = [DateTime]::UtcNow
$updateRecords = $False

for ($i = 0; $i -lt $records.Length; $i++)
{
    # Get user ADS path and date when to remove the user from group.
    $record = $records[$i]
    $path = ($record | Select-String -Pattern "Adaxes\:\/\/\<GUID=.+\>").Matches[0].Value
    $record = $record.Replace($path, "").Trim()
    $date = [Datetime]::FromFileTimeUtc($record)

    if ($date -le $currentDate -and ($Context.TargetObject.IsMember($path)))
    {
        # Remove user from group.
        $Context.TargetObject.Remove($path)
        $records[$i] = $NULL
        $updateRecords = $True
    }
}

if ($updateRecords)
{
    # Update list of users to remove.
    [System.String[]]$records = $records | ?{$_}
    $Context.TargetObject.PutEx("ADS_PROPERTY_UPDATE", $memberListProperty, $records)
    $Context.TargetObject.SetInfo()
}

Comments 9

You must be signed in to comment.

  • Jason

    Jason

    I am attempting to run the Custom Command script, and I am receiving the following error:

    "Method invocation failed because [softerra.adaxes.adsi.admuser] does not contain a method named Add".

    • Support

      Support

      Hello Jason,

      Looks like you configured your Custom Command for User Object type. You need to use the script in a Custom Command configured for Group Object type.

  • TB

    TB

    Hello,
    How can I change this script so heldesk can specify a user in parameter instead of using the initator?

    Thanks.

  • cccoder

    cccoder

    Hello,

    I try to customise the script to use custom Parameters. I want to pick up the user instead of using the initiator but I get some problem with this code :

    # Build initiator path  
    $guid = [Guid]$Context.%param-usertoadd%.UserAdsObject.Get("ObjectGuid") --> not working like this.  
    $initiatorPath = "Adaxes://<GUID=$guid>"  
    

    What's wrong with the syntax?

    Thank you.

    • Support

      Support

      Hello,

      If the usertoadd parameter is of AD object picker type, you need to use the following code to bind to the user specified in the parameter:

      $user = $Context.BindToObject("Adaxes://%param-usertoadd%")
      
      • cccoder

        cccoder

        Thank you :-)

        I did this :

        $user = $Context.BindToObject("Adaxes://%param-usertoadd%")  
        $guid = [Guid]$user.Get("objectGUID")  
        $initiatorPath = "Adaxes://<GUID=$guid>"
        

        The script returns no error but the group membership is not updated. The value adm-CustomAttributeTextMultiValue1 is setted in the group with a value like this :

        Adaxes:// 132123316309802111

  • cccoder

    cccoder

    I finally manage to get the first script working by changing this:

    #$Context.TargetObject.Add($Context.Initiator.UserAdsObject.AdsPath)  
    
    $Context.TargetObject.Add($initiatorPath)
    

    The second script give me an error about date format :

    Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime." Stack trace: at , : line 46 at , : line 46

    $dates = ($records[$i] | Select-String -Pattern "\d{2}\/\d{2}\/\d{4}\s\d{2}\s\d{2}\s.{2}" -AllMatches).Matches | %%{[DateTime]::ParseExact($_.Value, "MM/dd/yyyy hh mm tt", $NULL)}

    $dates = ($records[$i] | Select-String -Pattern "\d{2}\/\d{2}\/\d{4}\s\d{2}\s\d{2}\s.{2}" -AllMatches).Matches | %%{[DateTime]::ParseExact($_.Value, "MM/dd/yyyy hh mm tt", $NULL)}

    Maybe because I user European format dd/mm/yyyy?

Got questions?

Support Questions & Answers

We use cookies to improve your experience.
By your continued use of this site you accept such use.
For more details please see our privacy policy and cookies policy.