Validating a given username and password is a common task in many scripts. Online, there are several examples that make use of ValidateCredentials method of System.DirectoryServices.AccountManagement.PrincipalContext class. You could create an instance of this class in PowerShell and then call the method.
Here’s my version that uses PrincipalContext class:
# -- Get the full script here : https://github.com/VimalShekar/PowerShell/blob/master/CheckIsUserValid_1.ps1 | |
function IsLocalUserNamePasswordValid() | |
{ | |
param( | |
[String]$UserName, | |
[String]$Password | |
) | |
$DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext('machine',$ComputerName) | |
$bReturn = $DS.ValidateCredentials($UserName, $Password) | |
return $bReturn | |
} | |
function IsDomainUserNamePasswordValid() | |
{ | |
param( | |
[String]$UserName, | |
[String]$Password, | |
[String]$DomainName | |
) | |
$DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext('domain',$DomainName) | |
$bReturn = $DS.ValidateCredentials($UserName, $Password) | |
return $bReturn | |
} | |
#Example Usage: | |
#IsLocalUserNamePasswordValid -UserName TestLocalUser1 -Password Test@Pass1 | |
#IsDomainUserNamePasswordValid -UserName TestDomUser1 -Password Test@Pass1 -DomainName testdom.local |
The only problem with this is that this class is only available from .NET version 3.5. If you want this functionality on machines where .NET 3.5 is not installed, there’s another way to do it by using Win32 API.
Here’s another version of my script that checks if the given username and password is valid by using LogonUser Win32 API. It basically imports the API and then calls it.
# -- Get the full script here : https://github.com/VimalShekar/PowerShell/blob/master/CheckIsUserValid.ps1 | |
# This is used by some of the functions below | |
$logonUserSignature = | |
@' | |
[DllImport( "advapi32.dll" )] | |
public static extern bool LogonUser( String lpszUserName, | |
String lpszDomain, | |
String lpszPassword, | |
int dwLogonType, | |
int dwLogonProvider, | |
ref IntPtr phToken ); | |
'@ | |
$closeHandleSignature = | |
@' | |
[DllImport( "kernel32.dll", CharSet = CharSet.Auto )] | |
public static extern bool CloseHandle( IntPtr handle ); | |
'@ | |
$revertToSelfSignature = | |
@' | |
[DllImport("advapi32.dll", SetLastError = true)] | |
public static extern bool RevertToSelf(); | |
'@ | |
$AdvApi32 = Add-Type -MemberDefinition $logonUserSignature -Name "AdvApi32" -Namespace "PsInvoke.NativeMethods" -PassThru | |
$Kernel32 = Add-Type -MemberDefinition $closeHandleSignature -Name "Kernel32" -Namespace "PsInvoke.NativeMethods" -PassThru | |
$AdvApi32_2 = Add-Type -MemberDefinition $revertToSelfSignature -Name "AdvApi32_2" -Namespace "PsInvoke.NativeMethods" -PassThru | |
[Reflection.Assembly]::LoadWithPartialName("System.Security") | |
function IsLocalUserNamePasswordValid() | |
{ | |
param( | |
[String]$UserName, | |
[String]$Password | |
) | |
$Logon32ProviderDefault = 0 | |
$Logon32LogonInteractive = 2 | |
$tokenHandle = [IntPtr]::Zero | |
$success = $false | |
$DomainName = $null | |
#Attempt a logon using this credential | |
$success = $AdvApi32::LogonUser($UserName, $DomainName, $Password, $Logon32LogonInteractive, $Logon32ProviderDefault, [Ref] $tokenHandle) | |
return $success | |
} | |
function IsDomainUserNamePasswordValid() | |
{ | |
param( | |
[String]$UserName, | |
[String]$Password, | |
[String]$DomainName | |
) | |
$Logon32ProviderDefault = 0 | |
$Logon32LogonInteractive = 2 | |
$tokenHandle = [IntPtr]::Zero | |
$success = $false | |
#Attempt a logon using this credential | |
$success = $AdvApi32::LogonUser($UserName, $DomainName, $Password, $Logon32LogonInteractive, $Logon32ProviderDefault, [Ref] $tokenHandle) | |
return $success | |
} | |
#Example Usage: | |
#IsLocalUserNamePasswordValid -UserName TestLocalUser1 -Password Test@Pass1 | |
#IsDomainUserNamePasswordValid -UserName TestDomUser1 -Password Test@Pass1 -DomainName testdom.local |