Sunday, August 21, 2011

PowerShell: Test-UserCredential

Sometimes you may find it necessary to validate a user’s credentials before using them. I’ve created a simple PowerShell function to do just that and posted it to PoshCode. The script makes use of the PrincipalContext class in the System.DirectoryServices.AccountManagement namespace. Specifically, the ValidateCredentials method is used to determine whether not the provided credentials are valid against either the machines domain or local SAM database depending on whether the –Domain flag is specified or not.

Check out the script:

function Test-UserCredential {
[CmdletBinding(DefaultParameterSetName = "set1")]
[OutputType("set1", [System.Boolean])]
[OutputType("PSCredential", [System.Boolean])]
[Parameter(Mandatory=$true, ParameterSetName="set1", position=0)]
[String] $Username,

[Parameter(Mandatory=$true, ParameterSetName="set1", position=1)]
[System.Security.SecureString] $Password,

[Parameter(Mandatory=$true, ParameterSetName="PSCredential", ValueFromPipeline=$true, position=0)]
[Management.Automation.PSCredential] $Credential,

[Switch] $Domain,

[Switch] $UseKerberos

Begin {
try {
$assemType = 'System.DirectoryServices.AccountManagement'
$assem = [reflection.assembly]::LoadWithPartialName($assemType) }
catch { throw 'Failed to load assembly "System.DirectoryServices.AccountManagement". The error was: "{0}".' -f $_ }

$system = Get-WmiObject -Class Win32_ComputerSystem

if (0, 2 -contains $system.DomainRole -and $Domain) {
throw 'This computer is not a member of a domain.'

Process {
try {
switch ($PSCmdlet.ParameterSetName) {
'PSCredential' {
if ($Domain) {
$Username = $Credential.UserName.TrimStart('\')
} else {
$Username = $Credential.GetNetworkCredential().UserName
$PasswordText = $Credential.GetNetworkCredential().Password
'set1' {
# Decrypt secure string.
$PasswordText = [Runtime.InteropServices.Marshal]::PtrToStringAuto(

if ($Domain) {
$pc = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext 'Domain', $system.Domain
} else {
$pc = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext 'Machine', $env:COMPUTERNAME

if ($Domain -and $UseKerberos) {
return $pc.ValidateCredentials($Username, $PasswordText)
} else {
return $pc.ValidateCredentials($Username, $PasswordText, [DirectoryServices.AccountManagement.ContextOptions]::Negotiate)
} catch {
throw 'Failed to test user credentials. The error was: "{0}".' -f $_
} finally {
Remove-Variable -Name Username -ErrorAction SilentlyContinue
Remove-Variable -Name Password -ErrorAction SilentlyContinue

Validates credentials for local or domain user.

The user's username.

The user's password.

.PARAMETER Credential
A PSCredential object created by Get-Credential. This can be pipelined to Test-UserCredential.

If this flag is set the user credentials should be a domain user account.

.PARAMETER UseKerberos
By default NTLM is used. Specify this switch to attempt kerberos authentication.

This is only used with the 'Domain' parameter.

You may need to specify domain\user.

PS C:\> Test-UserCredential -Username andy -password (Read-Host -AsSecureString)

PS C:\> Test-UserCredential -Username 'mydomain\andy' -password (Read-Host -AsSecureString) -domain -UseKerberos

PS C:\> Test-UserCredential -Username 'andy' -password (Read-Host -AsSecureString) -domain

PS C:\> Get-Credential | Test-UserCredential




Revision History
2011-08-21: Andy Arismendi - Created.
2011-08-22: Andy Arismendi - Add pipelining support for Get-Credential.
2011-08-22: Andy Arismendi - Add support for NTLM/kerberos switch.

Test-UserCredential -user andy -password (Read-Host -AsSecureString)