# Description
Contractor accounts in Active Directory expire on a fixed date, and access usually gets cut off before anyone remembers to renew it. This plugin checks Active Directory every day for contractor accounts that expire in the next 14 days and messages each contractor's manager in the Moveworks AI Assistant. With one click, the manager extends the account for 6 months or lets it expire as planned. The plugin records the choice in Active Directory and logs a resolved ServiceNow incident as the audit trail. Managers don't have to file a ticket, and IT doesn't have to chase anyone down for an answer.
# User Experience Preview
Please refer to the following [**Purple Chat**](https://marketplace.moveworks.com/purple-chat?conversation=%7B%22startTimestamp%22%3A%229%3A00+AM%22%2C%22messages%22%3A%5B%7B%22role%22%3A%22assistant%22%2C%22parts%22%3A%5B%7B%22richText%22%3A%22%3Cp%3EJordan+Lee%27s+Windows+account+access+is+expiring+soon.+Click+below+to+extend+access+for+6+months.%3C%2Fp%3E%3Cp%3E%3Cb%3E%5BExtend+Access+for+6+months+for+Jordan%5D%3C%2Fb%3E+%26nbsp%3B+%3Cb%3E%5BDo+NOT+extend+Jordan%5D%3C%2Fb%3E%3C%2Fp%3E%22%7D%5D%7D%2C%7B%22role%22%3A%22user%22%2C%22parts%22%3A%5B%7B%22richText%22%3A%22Extend+Access+for+6+months+for+Jordan%22%7D%5D%7D%2C%7B%22role%22%3A%22assistant%22%2C%22parts%22%3A%5B%7B%22richText%22%3A%22%3Cp%3EDone.+Jordan+Lee%27s+account+has+been+extended+for+6+months%2C+and+the+change+is+logged+in+ServiceNow+as+%3Cb%3EINC0012345%3C%2Fb%3E+%28Resolved%29.%3C%2Fp%3E%22%7D%5D%7D%5D%7D) for a sample conversational experience between a user and the AI Assistant for this plugin.
# Pre-requisites
Before installing and using the **Extend Expiring Contractor Accounts** plugin, please ensure the following requirements are met:
## **1. Active Directory Connector**
This plugin requires a **Built-In Active Directory connector** that reaches your domain through the **Moveworks On-Prem Agent**. The connector's service account must be able to read user objects (`accountExpires`, `manager`, `mail`, `givenName`, `sn`, `distinguishedName`) and to change the membership of the two extension groups below. Built-In connectors must also be enabled for use in Tool Studio.
If you have not already configured the connector, please follow the [**Active Directory Connector Guide**](https://marketplace.moveworks.com/connectors/active-directory#how-to-implement). The connector must be fully set up before installing this plugin.
## **2. ServiceNow Connector**
This plugin requires an active **ServiceNow connector**. Its service account needs to create and resolve records in the `incident` table, because every decision is logged as a resolved incident with the manager as the caller.
If you have not already configured the connector, please follow the [**ServiceNow Connector Guide**](https://marketplace.moveworks.com/connectors/servicenow#how-to-implement).
## **3. Two Active Directory groups that drive account expiry**
The plugin doesn't change `accountExpires` itself. It adds the contractor to one of two groups, and your existing identity automation acts on that membership:
- An **extend** group. Your automation pushes `accountExpires` out by 180 days for its members.
- A **do-not-extend** group. Your automation lets these accounts expire on their current date.
Create both groups, or reuse ones you already have, before installing.
## **4. Managers in the Moveworks user directory**
Each contractor's `manager` attribute must point to a user whose `mail` matches a Moveworks user, because that's how the AI Assistant finds the person to notify. Contractors without a manager, or whose manager can't be found, are skipped.
Once the connectors are configured, follow our [**plugin installation documentation**](https://help.moveworks.com/docs/ai-agent-marketplace-installation) for detailed steps on how to install and activate the plugin in **Tool Studio**.
## **5. Settings to change after installing**
The plugin ships with placeholder values and its daily schedule **turned off**. In **Tool Studio**, update:
| Where | Setting | Change it to |
|---|---|---|
| `AD_Contract_Extender_Get_Expiring_Users_Template` | `base_object` | The OU that holds your contractor accounts, e.g. `OU=Contractors,DC=yourcompany,DC=com`. It must be an OU, not just the domain (`DC=…`), or the search fails. |
| `AD_Contract_Extender_Extend_Account_Template` | `entry` | The DN of your extend group |
| `AD_Contract_Extender_Decline_Extension_Template` | `entry` | The DN of your do-not-extend group |
| `AD_Contract_Extender_Extend_And_Ticket_Template` and `AD_Contract_Extender_Decline_And_Ticket_Template` | `assignment_group` | The ServiceNow group that owns these records (ships as `Service Desk`) |
| Plugin `AD_Contract_Extender_Template` | Schedule | Turn it on, and set the start time and time zone (it runs every 24 hours) |
# **Implementation Details**
## API Details
The Active Directory calls are HTTP actions that inherit the Built-In Active Directory connector. Their base URL, `https://ldap-service.moveworks.int`, isn't publicly reachable: Moveworks forwards each request to your domain through the On-Prem Agent. The ServiceNow call runs against your instance; replace `<YOUR_INSTANCE>` with your hostname and `<ACCESS_TOKEN>` with the connector's access token.
### **API #1: Find accounts expiring in the next 14 days**
Searches for enabled users with an email address whose `accountExpires` falls between now and 14 days from now. The plugin converts both dates to Windows FILETIME (100-nanosecond intervals since 1601-01-01).
```json
POST /ldap/v1/search
{
"base_object": "OU=Contractors,DC=yourcompany,DC=com",
"filter": "(&(objectClass=user)(objectCategory=Person)(mail=*)(accountExpires>={{start_date}})(accountExpires<={{end_date}})(!(accountExpires=0))(!(accountExpires=9223372036854775807))(!(userAccountControl:1.2.840.113556.1.4.803:=2)))",
"filter_args": { "start_date": "134292384000000000", "end_date": "134304480000000000" },
"attributes": ["distinguishedName", "mail", "givenName", "sn", "manager", "accountExpires", "division"]
}
```
**Request body:**
- `base_object` *(string, required):* the OU to search. It must include an OU.
- `filter` *(string, required):* LDAP filter template. It excludes never-expiring accounts (`0` and `9223372036854775807`) and disabled accounts.
- `filter_args` *(object, required):* the FILETIME window. The platform escapes these values before inserting them into the filter.
**Key nuances:**
- Attribute values come back as arrays, e.g. `mail[0]`.
- Every run re-notifies each account still in the 14-day window, so a manager who doesn't act hears about it again the next day.
### **API #2: Look up the manager**
Reads the manager's entry from the contractor's `manager` DN to get their email address.
```json
POST /ldap/v1/search
{ "base_object": "CN=Doe\\, Jane,OU=Users,DC=yourcompany,DC=com", "filter": "(objectClass=*)", "attributes": ["distinguishedName", "mail", "givenName", "manager", "accountExpires"] }
```
**Key nuances:**
- If the lookup fails, the contractor is skipped and the run continues.
### **API #3: Extend the account**
Runs when the manager clicks **Extend**. It adds the contractor to the extend group.
```json
PUT /ldap/v1/modify
{ "entry": "CN=Contract-Extension-180-Days,OU=Groups,DC=yourcompany,DC=com", "add": { "member": ["CN=Doe\\, Jane,OU=Users,DC=yourcompany,DC=com"] } }
```
**Key nuances:**
- Returns `204 No Content`. The account's expiry date changes only when your group automation runs.
### **API #4: Let the account expire**
Runs when the manager clicks **Do NOT extend**. It's the same call against the do-not-extend group.
```json
PUT /ldap/v1/modify
{ "entry": "CN=Contract-Extension-Do-Not-Extend,OU=Groups,DC=yourcompany,DC=com", "add": { "member": ["CN=Doe\\, Jane,OU=Users,DC=yourcompany,DC=com"] } }
```
### **API #5: Log the decision in ServiceNow**
Creates a resolved incident recording which manager made which choice, for whom.
```bash
curl --location 'https://<YOUR_INSTANCE>/api/now/table/incident' \
--header 'Authorization: Bearer <ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"short_description": "Contract Extension",
"description": "jane.doe@example.com'"'"'s windows account was extended for 6 months by john.manager@example.com",
"caller_id": "john.manager@example.com",
"contact_type": "virtual_agent",
"assignment_group": "Service Desk",
"state": "Resolved",
"close_code": "Solution provided",
"close_notes": "Fulfilled by AD Contract Extender"
}'
```
**Request body:**
- `caller_id` *(string):* the manager's email address.
- `assignment_group`, `state`, `close_code` *(string):* set by the plugin. Change them to match your instance.
**Key nuances:**
- `state`, `caller_id` and `assignment_group` are sent as display values. If your instance only accepts sys_ids here, add the query parameter `sysparm_input_display_value=true` to the action.
### API References
For request parameters, response formats and error handling, refer to the [**Tool Studio LDAP HTTP actions**](https://docs.moveworks.com/tool-studio/actions/http-actions/http-ldap-actions) documentation and the official [**ServiceNow Table API**](https://www.servicenow.com/docs/bundle/zurich-api-reference/page/integrate/inbound-rest/concept/c_TableAPI.html) documentation.
# **What Is In Scope for This Plugin?**
- A daily search of one Active Directory OU for enabled contractor accounts that expire in the next 14 days
- A chat notification to each contractor's manager, with **Extend** and **Do NOT extend** buttons
- Adding the contractor to an extend group or a do-not-extend group
- Logging each decision as a resolved ServiceNow incident
# **What Is Out of Scope for This Plugin?**
- Changing `accountExpires` directly. Your group-driven automation does that.
- Extension lengths other than the one your extend group applies (6 months as shipped)
- Microsoft Entra ID (Azure AD) cloud-only accounts
- Employees asking about their own account in chat. The plugin only notifies managers, on a schedule.
- Grouping several contractors into one message per manager. Each contractor gets their own notification.
- Removing a contractor from a group after a decision, or undoing a decision
# Related Plugins
| Plugin | What it does |
|---|---|
| [Remind about Expiring Contractors](https://marketplace.moveworks.com/plugins/microsoft-entra-contractor-expiry-reminders) | Design guide for reminding managers about expiring contractors in Microsoft Entra |