If you enable Smart Card authentication in UAG you might run into a problem where UAG allows users access even though the Active Directory account is disabled. In this post I will show you how I solved that problem at a customer.
If you follow the TechNet guide to Configuring SSL client certificate authentication you will find that UAG will allow access to a user even if the account is disabled or locked in Active Driectory. As long as the certificate is ok and mappes to a user in AD it will allow access. At a customer of mine this was not the wanted scenario and they did not want to revoce the certificates either since certificates (Smart Cards) where distributed to vendors and other non-employees. They wanted to be able to disable the AD account and thereby denying access to the UAG portal.
The Solution
In the guide (step 7) you will find that you will make a copy of the repository_for_cert.inc template and rename it to the Authentication_Server_Name.inc. In that file the first function is called CheckCredentials looking like this.
function CheckCredentials(user_name,password)
if user_name = "" then
CheckCredentials = false
SendFailToAuthenticateMsg "Did not get user name"
else
CheckCredentials = true
end if
end function
What I did was to add a new function call to this function getting something like this.
function CheckCredentials(user_name,password)
if user_name = "" then
CheckCredentials = false
SendFailToAuthenticateMsg "Did not get user name"
else
Accountlock = CheckAccountlock(user_name)
if Accountlock = true then
CheckCredentials = false
SendFailToAuthenticateMsg "Account disabled in AD"
else
CheckCredentials = true
end if
end if
end function
The SendFailToAuthenticateMsg “Account disabled in AD” will show in the logs of UAG and will tell you why the authentication failed.
The new function CheckAccountLock gave me a problem. UAG does not run this as an account with access to AD. So I ended up creating a read-only service account I could tell my function to use to check the user account in AD. The final function looked something like this.
function CheckAccountlock(user_name)
Const ADS_UF_ACCOUNTDISABLE = &H0002
'create connection
set connAD = CreateObject("ADODB.Connection")
connAD.Provider = "ADsDSOObject"
connAD.Properties("User ID") = "AD\UAG_ReadAD"
connAD.Properties("Password") = "SomePassword"
connAD.Properties("Encrypt Password") = true
connAD.Open
'Search user
strBase = "<LDAP://DC=ad,DC=company,DC=com>"
strFilter = "(sAMAccountName=" & user_name & ")"
strAttributes = "sAMAccountName,userAccountControl"
strScope = "subtree"
strFullCommand = strBase & ";" & strFilter & ";" & strAttributes & ";" & strScope
set rsADUserInfo = CreateObject("ADODB.Recordset")
set rsADUserInfo = connAD.Execute(strFullCommand)
if not rsADUserInfo.EOF then
uac = rsADUserInfo("userAccountControl")
end if
if uac AND ADS_UF_ACCOUNTDISABLE Then
CheckAccountlock = true
Else
CheckAccountlock = false
end if
'Close
set rsADUserInfo = Nothing
connAD.Close
set connAD = Nothing
end function
I do think that there are more elegant ways of solving this problem. But time in this case was short and I was happy to have solved the customers problem. Feel free to comment if you have some ideas on how to improve this solution.