powershellwhile-loopscripting

Having some trouble trying to verify credentials from get-credentials. Is there a better way?


I thought my script worked in test environment (it prompted me for credentials again and again when I mistyped, but accepted them after I typed them correctly). But when I tried to use it in production, it just keeps prompting me over and over even when I type my credentials correctly.

Am I doing something wrong? Is there a better way? (Sorry for bad formatting. I’m on mobile)

$Message = 'Please type your credentials?'

While (!$CredentialValidation){

  $UserCredential = Get-Credential -Message $Message

  $UserCredential | Export-Clixml -Path "C:\Temp\creds.xml"

  $Ausername = $UserCredential.username 
  $Apassword = $UserCredential.GetNetworkCredential().password

  $CurrentDomain = "LDAP://" + ([ADSI]"").distinguishedName

  $Domain = New-Object System.DirectoryServices.DirectoryEntry($CurrentDomain, $Ausername, $Apassword)

  If ($Domain.name -eq $null){
    $Message = "You’ve mistyped your credentials!”

  }
  else{
    $CredentialValidation = $true
  }
} 

Write-Host "Credentials verified. Moving to next step”

Solution

  • Your code looks fine, I'd personally use PrincipalContext.ValidateCredentials Method as it's a dedicated API for validation, but do note what is stated in Remarks from this documentation:

    The userName argument must take the form userName (for example, mcampbell) rather than domain\username or username@domain.

    You could also use a function to validate the credentials, this could make the code easier to read and understand.

    Here is how you could approach it:

    function Test-Credential {
        param(
            [Parameter(Mandatory)]
            [System.Management.Automation.CredentialAttribute()]
            [pscredential] $Credential,
    
            [Parameter()]
            [ValidateSet('Domain', 'Machine')]
            [string] $ContextType = 'Domain'
        )
    
        Add-Type -AssemblyName System.DirectoryServices.AccountManagement -ErrorAction Stop
    
        try {
            $context = [System.DirectoryServices.AccountManagement.PrincipalContext]::new($ContextType)
            $context.ValidateCredentials(
                $Credential.UserName,
                $Credential.GetNetworkCredential().Password)
        }
        catch {
            $PSCmdlet.WriteError($_)
        }
        finally {
            if ($context) {
                $context.Dispose()
            }
        }
    }
    
    $pathToCreds = 'C:\Temp\creds.xml'
    
    while ($true) {
        $cred = Get-Credential -Message 'Please type your credentials?'
    
        # if no credentials were supplied or empty password,
        # go to next iteration, ask again
        if (-not $cred -or $cred.Password.Length -eq 0) {
            continue
        }
    
        # if the credentials are correct
        if (Test-Credential $cred) {
            # store them
            $cred | Export-Clixml -Path $pathToCreds
            # and end the loop
            break
        }
    
        # else, wrong creds message and next loop iteration
        Write-Host "You've mistyped your credentials!" -ForegroundColor Red
    }
    
    Write-Host 'Credentials verified. Moving to next step' -ForegroundColor Green