Monday, November 21, 2011

Disabled Users in AD and WCI Portal

How to Prevent Disabled users from getting synchronized in Portal?
We recently stumbled upon a major issue with our Oracle WCI portal. We found that users who had long since left the company had their portal accounts present. The accounts were disabled but still they were present in the portal and therefore visible during searches.

Our initial thought had been that either there was something wrong with the AD or that our portal’s synchronization job was not functioning properly. However we spent some time with Google and came upon a very interesting thing. Microsoft’s AD has a limitation that you can define only one folder in your AD user query. I will explain this with an example below.



The normal structure of any companies AD looks similar to the one as below:






Now all users who work for the company are created under the Accounts folder. Now what happens when a person leaves the company? Yes, the account of the person is disabled and moved to a separate folder called Archive-Disabled. However this folder is a sub-folder of the Accounts OU folder in Active Directory.
The limitation I had mentioned earlier means that the User Query can point to one folder at a time and in our case it is the root folder called Accounts. You cannot make your user query point selectively to all folders under Accounts while explicitly not mentioning the Disabled sub folder.


Here are the original settings we had for our portal’s Authentication source and Profile Source.
Original Settings of Authentication Source
User Query Filter - (&(objectcategory=person)(objectclass=user))
Original Settings of Profile Source
User Query Filter - (&(objectcategory=person)(objectclass=user))


Microsoft AD has a work around for the issue so that even though your user query points to the root folder, it will look for a bitwise filter property which signals if the account is enabled or disabled. Then whenever the AD Synch and AD Profile Synch jobs will run, it will import only enabled users from the Accounts OU while discarding all disabled users from the OU.


Here are the modified settings:
New Settings of Authentication Source
User Query Filter - (&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))
New Settings of Profile Source
User Query Filter - (&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))


The value 1.2.840.113556.1.4.803 is the LDAP_MATCHING_RULE_BIT_OR rule. After user query filter had been modified and the jobs ran, it worked as a dream and only enabled users were brought into the portal.


Just to let you guys know:
1.2.840.113556.1.4.803 - This is the LDAP_MATCHING_RULE_BIT_AND rule. The matching rule is true only if all bits from the property match the value. This rule is like the bitwise AND operator.
1.2.840.113556.1.4.804 - This is the LDAP_MATCHING_RULE_BIT_OR rule. The matching rule is true if any bits from the property match the value. This rule is like the bitwise OR operator.

Some more examples of AD filters that can be used as are follows:
Example LDAP User Filters
~ Default user filter:(&(objectCategory=Person)(objectClass=User))
~ Exclude accounts with no email address:(&(objectCategory=Person)(objectClass=User)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(mail=*))
~ Exclude disabled accounts:(&(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2))
~ Exclude accounts with passwords set to expire:(&(objectCategory=person)(objectClass=user)(!userAccountControl=65536))
~ Include only the accounts with valid email addresses(&(objectCategory=Person)(objectClass=User)(mail=*com)
~ Include only the accounts that are part of the Branch1 organizational unit(&(objectCategory=Person)(objectClass=User)(memberof:1.2.840.113556.1.4.1941:=(CN=Authenticated Users,OU=Branch1,DC=domain,DC=local)))
~ Exclude accounts that don’t have a first name (&(objectCategory=Person)(objectClass=User)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(!givenName=*)))

PS: Thanks to Guru Geoff Garcia for helping me with this issue. :) :)