When building Windows services that need to impersonate users across trusted domains (without full delegation), many developers hit a wall with Active Directory permissions. The critical permission you're looking for is "Impersonate a client after authentication" (SeImpersonatePrivilege), but it's often misunderstood by AD admins.
Here's how to properly configure this for a service account named svc_myapp@primarydomain.com
that needs to impersonate Barnie@otherdomain.com
:
# PowerShell to grant the right
Import-Module ActiveDirectory
$serviceAccount = Get-ADUser -Identity "svc_myapp"
$targetAccount = Get-ADUser -Identity "Barnie" -Server "otherdomain.com"
# This is the magic permission:
$impersonationRight = [System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight
$objectType = [Guid]"72e39547-7b18-11d1-adef-00c04fd8d5cd" # Impersonation GUID
$acl = Get-Acl "AD:\$($targetAccount.DistinguishedName)"
$ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
$serviceAccount.SID,
$impersonationRight,
"Allow",
$objectType
)
$acl.AddAccessRule($ace)
Set-Acl -AclObject $acl -Path "AD:\$($targetAccount.DistinguishedName)"
- Cross-domain issues: Ensure proper trust relationships exist between domains
- Service Principal Names (SPNs): Verify no duplicate SPNs exist for the service account
- Token size limitations: Large group memberships may cause authentication failures
Use this C# snippet to verify impersonation works:
using System.Security.Principal;
WindowsIdentity.RunImpersonated(targetUserAccessToken, () => {
// This code runs as Barnie@otherdomain.com
Console.WriteLine($"Current user: {WindowsIdentity.GetCurrent().Name}");
// Perform domain-specific operations here
});
Always follow least-privilege principles:
- Limit impersonation to specific target accounts (not entire groups)
- Implement proper auditing of impersonation events
- Consider using Constrained Delegation instead if appropriate
When you need a service account to impersonate another user across domains (without full Kerberos delegation), you're dealing with Windows security primitives at a deep level. The key permission required is SeImpersonatePrivilege
, often referred to as "Act as part of the operating system" in policy settings.
# PowerShell snippet to verify current privileges
whoami /priv | findstr /i "Impersonate"
To grant this programmatically:
# Using Group Policy Management Console (manual way):
1. Open "Local Security Policy" (secpol.msc)
2. Navigate to: Local Policies → User Rights Assignment
3. Find "Act as part of the operating system"
4. Add your service account
# Alternative ADSI Edit method for cross-domain scenarios:
$de = New-Object DirectoryServices.DirectoryEntry("LDAP://CN=Default Domain Controllers Policy,CN=Policies,CN=System,DC=domain,DC=com")
$de.Properties["privilegeRights"].Value = @("SeImpersonatePrivilege=YourServiceAccount")
$de.CommitChanges()
For a service account (SVC_AppPool) needing to impersonate Barney@otherdomain.com:
// C# impersonation code sample
WindowsIdentity foo = new WindowsIdentity("Barney@otherdomain.com");
WindowsImpersonationContext ctx = foo.Impersonate();
try {
// Perform actions as Barney
File.WriteAllText(@"\\otherdomain\share\test.txt", "Impersonated!");
}
finally {
ctx.Undo();
}
- The service account becomes extremely privileged - treat it as Tier 0
- Never grant this to regular user accounts
- Audit usage via SACL on sensitive resources
- Consider constrained delegation instead if possible
If you get ACCESS_DENIED even after configuration:
# Check effective permissions with:
CheckAcces.exe -u SVC_AppPool -t Barney@otherdomain.com
# Verify cross-domain trust is properly configured:
nltest /domain_trusts /all_trusts