For an internal application using Windows Authentication, I am able to get a WindowsPrincipal object in C# using this code:
var winPrincipal = (WindowsPrincipal)HttpContext.Current.User;
Is this information (including Sam name and domain groups the user is in, which is included on this object) communicated to IIS directly from the user's computer, or does IIS have to query LDAP?
I've found that Querying LDAP from application code is not a free operation, so I'm wondering if this adds some overhead to a request if IIS is querying LDAP to construct the WindowsPrincipal object, and if it's not querying LDAP then does that introduce any security issues if I just trust the WindowsPrincipal object from IIS without querying LDAP (i.e. could an attacker potentially add groups they aren't really in to their ticket on the request)?
Windows Authentication uses the access token from the user's computer, but the server does verify that it is valid.
The authentication groups are stored in the token, so that doesn't make an LDAP request.
If you need any information from the user's account that isn't stored in the token, then you do need to make an LDAP request yourself. The most efficient way is to bind directly to the user's object using the SID, which you already have:
var identity = (WindowsIdentity) HttpContext.Current.User.Identity;
var user = new DirectoryEntry($"LDAP://<SID={identity.User.Value}>");
//Ask for only the attributes you want to read.
//If you omit this, it will end up getting every attribute with a value,
//which is unnecessary.
user.RefreshCache(new [] { "givenName", "sn" });
var firstName = user.Properties["givenName"].Value;
var lastName = user.Properties["sn"].Value;
If you're worried about efficiency when making LDAP requests, I wrote an article a while ago that discusses that: Active Directory: Better performance