The System.Security.Principal.IdenityNotMappedException seems to come up time to time and I thought I would write about what this exception means and how to resolve the issue.
The first thing to understand is that in Windows, User Accounts and Groups have a unique and immutable identifier known as a Security Identifier (SID). (You can find more information on SIDs at http://msdn.microsoft.com/en-us/library/windows/desktop/aa379571(v=vs.85).aspx) When working with User Accounts and Groups in Windows, you can work with them via their SID or by their name.
In Windows, a user is represented by an Access Token (You can find more information on Access Tokens at http://msdn.microsoft.com/en-us/library/windows/desktop/aa374909(v=vs.85).aspx) which can be associated with a process or to a thread (via impersonation). The token contains the user’s SID and all the Groups the user is a member of. The token contains the Group SIDs. (The groups are NOT stored by their names)
There are Win32 APIs that allow an application to translate between the name and the SID.
LookupAccountName() is used to translate from a Name to a SID
LookupAccountSid() is used to translate a SID to a Name
These Win32 APIs actually calls the LSA APIs. (One difference with these APIs is that they do allow you to translate multiple names/SIDs versus just one.)
When converting between a Name and a SID and vice versa, you can encounter an error if the translation can’t be done. The common Win32 Error code that you will see is 1332 also known as ERROR_NONE_MAPPED which translates to “No mapping between account names and security IDs was done.”
At the LSA API level where status errors are returned, the error is:
STATUS_NONE_MAPPED or STATUS_SOME_NOT_MAPPED
In .NET, the error code is mapped as the following exception:
Why would the translation APIs fail? Well, the API remarks provides some details on how the translation is done. It uses a lookup order to translate (there is also a local cache as well)
In addition to looking up SIDs for local accounts, local domain accounts, and explicitly trusted domain accounts, LsaLookupSids can look up SIDs for any account in any domain in the Windows forest, including SIDs that appear only in the SIDhistory field of an account in the forest. The SIDhistory field stores the former SIDs of an account that has been moved from another domain. To perform these searches, the function queries the global catalog of the forest.
So a translation failure could happen if you have an issue with your Domain(s) or an issue with SID History.
So the first step in determining the issue is identifying which user or SID is the issue. Once you have identified the User or SID, you can then review its relationship with the caller (who is this and what domain do they belong to and what domain does the system belong to where the caller is running)
Finally, a word of advice, internally most APIs are going to be working with SIDs so you can avoid the translation error and improve performance by always trying to work with SIDs.
You’ll notice that most classes in .NET such as IsInRole() allows you to specify a SID instead of the name (via the SecurityIdentifier class). WindowsIdentity.Groups allows you access to the SID as well.