Jean-Yves Moschetto's blog

Tip and tricks on Microsoft products

NAVIGATION - SEARCH

Authenticating users with smartcard and login/password

Context

When a user opens an Active Directory session with his smartcard, it happens that some applications do not support smartcard logon, but needs classical user/password login.

Dilemma

When you use Active Directory Users and Computers MMC, you only have the option "Smart Card is required for interactive logon":

This action does the following:

  • Disable logon with password
  • Change the user password
  • User does not password expiration date

Solution

User modification

Do not change user with ADUC MMC

Change users properties with a PowerShell Script

  $oUser = [ADSI]("LDAP://" + $Props.distinguishedname)
  Write-Output "Found user: $($oUser.DistinguishedName)"
  
  Write-Output "   --> Setting SMARTCARD_REQUIRED (No password change)"
  [int]$userFlags = $oUser.useraccountcontrol[0]
  $oUser.useraccountcontrol = $userFlags -bor $ADS_UF_SMARTCARD_REQUIRED
  $oUser.setinfo()
  
  #    $oUser.ObjectSecurity
  $self = [System.Security.Principal.SecurityIdentifier]'S-1-5-10'
  [guid]$nullGuid = [guid]"00000000-0000-0000-0000-000000000000"
  
  Write-Output "   --> Changing rights and attributes"
  $oUser.get_ObjectSecurity().AddAccessRule($(New-Object DirectoryServices.ActiveDirectoryAccessRule `
      $self, "ExtendedRight", "Allow", $(GetADRightGuid("Reset Password"))  `
   ))
  
  $oUser.get_ObjectSecurity().AddAccessRule($(New-Object DirectoryServices.ActiveDirectoryAccessRule `
   $self, "ExtendedRight", "Allow", $(GetADRightGuid("Change Password"))  `
   ))
  
  $oUser.CommitChanges()

Check password expires

On the OU in which the account is, link a GPO with a PowerShell login script and add the equivalent script:

  $oUser = SearchAD -ADSearchBase $RootDSE.defaultNamingContext `
        -ADFilter "(&(objectClass=user)(objectcategory=person)(sAMAccountName=$($env:username)))" `
        -ADProperties "distinguishedname", "displayname", "samAccountName", "useraccountcontrol", "objectGUID", "PwdLastSet"
  
  $PwdLastSet = ([DateTime]::FromFileTime([Int64]::Parse($oUser.Properties["pwdlastset"])))
  $UF = [int32]$oUser.Properties["useraccountcontrol"][0]
  $bSmartCard = ($UF -bor 0x40000) -eq $UF
  $bExpiresPassword = ($UF -bor 0x10000) -eq $UF
  
  $pwdAge = (get-date) - $pwdLastSet
  $OutBox.AppendText("   --> DistinguishedName           : $($oUser.Properties["distinguishedname"])`n")
  $OutBox.AppendText("   --> DisplayName                 : $($oUser.Properties["displayname"])`n")
  $OutBox.AppendText("   --> Password expires            : $($bExpiresPassword)`n")
  $OutBox.AppendText("   --> Requires SmartCard          : $($bSmartCard)`n")
  $OutBox.AppendText("   --> Password date        (UTC)  : $($pwdLastSet)`n")
  $OutBox.AppendText("   --> Password age                : $($pwdAge.Days) Days $($pwdAge.Hours) Hours $($pwdAge.Minutes) Mn

Add comment