Introduction

Just-In-Time (JIT) Administration on Windows Server 2016 is a Privileged Access Management (PAM) model that grants elevated privileges only when needed and only for the minimum time required to complete a task. Using the PAM feature in Active Directory (introduced in Windows Server 2016), administrators request time-limited group membership that expires automatically after a defined duration — typically minutes to hours. Combined with Microsoft Identity Manager (MIM) or manual PowerShell workflows, JIT administration dramatically reduces the attack window for privileged credential abuse.

Enabling the PAM Feature

The PAM optional feature must be enabled at the forest level before JIT administration is available:

# Check current forest functional level (must be Windows Server 2016)
(Get-ADForest).ForestMode

# Enable the PAM optional feature
Enable-ADOptionalFeature 'Privileged Access Management Feature' `
    -Scope ForestOrConfigurationSet `
    -Target 'contoso.com'

# Verify the feature is enabled
Get-ADOptionalFeature 'Privileged Access Management Feature' |
    Select-Object Name,IsDisableable,EnabledScopes

Creating a JIT-Ready Shadow Group

Create shadow security groups in a separate PAM bastion forest OU for JIT role assignments:

# Create a shadow domain admin group for JIT usage
New-ADGroup -Name 'JIT-DomainAdmins' `
    -SamAccountName 'JIT-DomainAdmins' `
    -GroupScope Global `
    -GroupCategory Security `
    -Path 'OU=JIT-Groups,OU=Admin,DC=contoso,DC=com' `
    -Description 'JIT time-limited Domain Admins membership group'

# Create JIT groups for common privileged roles
foreach ($role in @('Backup-Operators','Server-Operators','DnsAdmins','DHCP-Admins')) {
    New-ADGroup -Name "JIT-$role" `
        -SamAccountName "JIT-$role" `
        -GroupScope Global `
        -GroupCategory Security `
        -Path 'OU=JIT-Groups,OU=Admin,DC=contoso,DC=com'
}

Granting Time-Limited Membership

Add a user to a privileged group with an automatic time-to-live expiry:

# Grant jsmith membership in JIT-DomainAdmins for 2 hours
Add-ADGroupMember -Identity 'JIT-DomainAdmins' -Members 'jsmith' `
    -MemberTimeToLive (New-TimeSpan -Hours 2)

# Grant for specific task duration (30 minutes)
Add-ADGroupMember -Identity 'JIT-Backup-Operators' -Members 'b.jones' `
    -MemberTimeToLive (New-TimeSpan -Minutes 30)

# Check current time-limited memberships
Get-ADGroup 'JIT-DomainAdmins' -Properties Member |
    Select-Object -ExpandProperty Member |
    ForEach-Object { Get-ADObject $_ -Properties memberof,msDS-RidSetReferences }

Building a JIT Request Workflow

Create a PowerShell function to implement a self-service JIT request workflow:

function Request-JITAccess {
    param(
        [Parameter(Mandatory)][string]$Role,
        [Parameter(Mandatory)][string]$Justification,
        [int]$DurationHours = 1
    )

    $jitGroups = @{
        'DomainAdmin'    = 'JIT-DomainAdmins'
        'BackupOperator' = 'JIT-Backup-Operators'
        'ServerOperator' = 'JIT-Server-Operators'
        'DnsAdmin'       = 'JIT-DnsAdmins'
    }

    if (-not $jitGroups.ContainsKey($Role)) {
        Write-Error "Unknown JIT role: $Role. Valid roles: $($jitGroups.Keys -join ', ')"
        return
    }

    $requester = $env:USERNAME
    $groupName = $jitGroups[$Role]

    # Log the request to a central audit file
    $logEntry = [PSCustomObject]@{
        Timestamp   = (Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
        Requester   = $requester
        Role        = $Role
        Group       = $groupName
        Duration    = $DurationHours
        Justification = $Justification
        ExpiresAt   = (Get-Date).AddHours($DurationHours).ToString('yyyy-MM-dd HH:mm:ss')
    }
    $logEntry | Export-Csv -Path '\DC01JIT-Auditjit_requests.csv' -Append -NoTypeInformation

    # Grant time-limited access
    Add-ADGroupMember -Identity $groupName -Members $requester `
        -MemberTimeToLive (New-TimeSpan -Hours $DurationHours)

    Write-Host "[JIT] Access granted: $requester added to $groupName for $DurationHours hour(s)"
    Write-Host "[JIT] Access expires: $($logEntry.ExpiresAt)"
}

# Usage
Request-JITAccess -Role 'DnsAdmin' -Justification 'Emergency DNS zone update ticket INC0012345' -DurationHours 1

Auditing JIT Access Usage

Monitor JIT group membership changes with security event logging:

# Enable audit of security group changes
auditpol /set /subcategory:"Security Group Management" /success:enable /failure:enable

# Query security events for JIT group membership changes
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4728,4729,4732,4733} -MaxEvents 100 |
    Where-Object { $_.Message -like '*JIT-*' } |
    Select-Object TimeCreated,
        @{N='User';E={$_.Properties[0].Value}},
        @{N='Group';E={$_.Properties[2].Value}},
        @{N='ChangedBy';E={$_.Properties[6].Value}} |
    Format-Table -AutoSize

# Check membership TTL (time remaining)
Get-ADGroupMember -Identity 'JIT-DomainAdmins' -Properties memberTTL

Summary

Just-In-Time Administration on Windows Server 2016 fundamentally changes how privileged access is managed — from standing permanent membership to on-demand, time-limited grants. The AD PAM feature’s MemberTimeToLive attribute ensures access automatically revokes without manual intervention, closing the window of opportunity for attackers to abuse stolen credentials. Combined with a request workflow, justification logging, and audit trail, JIT administration is one of the most impactful controls in a privileged access management programme.