UserPrincipal.GetGroups vs. UserPrincipal.GetAuthorizationGroups? - c#

I am using ASP.Net 4.0 MVC to query active directory. I am trying to get a list of a user's group memberships and that iterate through them. I am having a weird problem. To get the groups I was using:
PrincipalSearchResult<Principal> groups = up.GetGroups();
Which worked great on localhost but returns an empty set when moved to IIS6. So I tried using this:
PrincipalSearchResult<Principal> groups = up.GetAuthorizationGroups();
Which worked great on IIS6 but returns an empty set on localhost. What is the difference between these 2 methods? Why can I use one in IIS6 and not on localhost? Why can I use the other one on localhost and not in IIS6?

The why part has been answered, but this may help someone wanting to know the functional difference between the two methods. From MS documentation:
GetGroups - Returns a collection of group objects that specify the groups of which the current principal is a member.
This overloaded method only returns the groups of which the principal is directly a member; no recursive searches are performed.
GetAuthorizationGroups - Returns a collection of principal objects that contains all the authorization groups of which this user is a member. This function only returns groups that are security groups; distribution groups are not returned.
This method searches all groups recursively and returns the groups in which the user is a member. The returned set may also include additional groups that system would consider the user a member of for authorization purposes.
So GetGroups gets all groups of which the user is a direct member, and GetAuthorizationGroups gets all authorization groups of which the user is a direct or indirect member.
Despite the way they are named, one is not a subset of the other. There may be groups returned by GetGroups not returned by GetAuthorizationGroups, and vice versa.

I assume GetAuthorizationGroups() calls in to tokenGroups in AD. To read that, your service account (or IIS machine account if Network Service) needs to be in the Windows Authorization Access group in AD.

Related

WindowsIdentity - Difference between Groups and Claims

I'm trying to check whether the User belongs to some groups by using SID-s.
I was using WindowsIdentity.Groups, but then noticed that sometimes it doesn't show that the user belongs to the Administrators group.
After searching a while, I've discovered that instead WindowsIdentity.Claims work fine (includes the admin group in the results as well).
I wasn't able to find proper documentation on Claims.
So, what is the difference between the Groups and Claims in WindowsIdentity, and why groups don't show administrators group while the Claims do?
And finally, can I safely use Claims instead of Groups?
Here's the code I have:
var wi = WindowsIdentity.GetCurrent();
var sidToFind = "S-1-5-32-544"; // Hardcoded the sid of administrators group for demo, but in general this is a parameter of a function on my side
// This will NOT include the sid S-1-5-32-544
var groupSids= wi.Groups
.Where(item => item.Value == sidToFind);
// This will include the sid S-1-5-32-544 and also all the other results that Groups provides.
var claimSids = wi.Claims
.Where(item => item.Value == sidToFind));
There are differencies between groups and claims.
Groups work with WORKGROUP and AD
Claims work with Active Directory Federation Services
Claims is more complex way to check user identity, because claims exists not only for ADFS, you can use or create additional claims token provider
When we call Groups method for WindowsIdentity, we have restriction:
// Ignore disabled, logon ID, and deny-only groups.
The role of claims
In the claims-based identity model, claims play a pivotal role in the
federation process, They are the key component by which the outcome of
all Web-based authentication and authorization requests are
determined. This model enables organizations to securely project
digital identity and entitlement rights, or claims, across security
and enterprise boundaries in a standardized way.
So, if you work only in NTLM - you can safty work with Groups, but if you want work via federation (for example SharePoint, Google, etc) - you must use claims. Claims contains groups, but groups not contain claims.
In order to answer the question why you do not see a certain group, you need to know its properties and location. As I wrote above and gave the link, there are restrictions on getting the list of groups. But here i found this info:
SID
Name
Description
S-1-5-32-544
Administrators
A built-in group. After the initial installation of the operating system, the only member of the group is the Administrator account. When a computer joins a domain, the Domain Admins group is added to the Administrators group. When a server becomes a domain controller, the Enterprise Admins group also is added to the Administrators group.
So, if your local admins group is disabled - you cannot see it when you get it via WindowsIdentity even if the user is included in it.

Ldap exchange group

I just want to ask you what is exactly exchange group in LDAP (if I use correctly the term and if the term exists) and how to query to get only exchange groups using ldap?
The client emphasize on it so I need to understand it and to know how to retrieve it.
Thank you in advanced.
You're talking about the Active Directory LDAP, correct?
A group in AD can be either distribution (i.e. exchange-only) or security.
Also, a group can be one of the 3 scopes: Universal, Global and Domain local. Here's the doc with the differences. A universal security groups can be mail-enabled, to act as a distribution group.
To query for all mail-enabled groups in a domain/container regardless of the group type, you can search for (&(objectClass=group)(proxyAddresses=*))

DotNetOpenAuth ClaimedIdentifier changes? What should I store in database to identify users

There are quite a few questions like this and this which all claims that ClaimedIdentifier should be used to uniquely identify each user.
After successful login I am storing ClaimedIndentifier in database. Whenever a user logs in, I traverse through my records looking for the ClaimedIdentifier. However I noticed that ClaimedIdentifiers are changing. What should I store in database to identify my users. I am using Google account.
This is how I am retrieving storing it into database
OpenIdRelyingParty rp = new OpenIdRelyingParty();
IAuthenticationResponse r = rp.GetResponse();
UserController.addUser(new UserController.User(r.ClaimedIdentifier.ToString(), 0));
This isn't a DotNetOpenAuth unique issue. This is a Google behavior. Google's OpenID Provider issues what are called pairwise-unique identifiers. They will always be the same for a given user so long as your OpenID realm is constant.
If you log users in without explicitly supplying a realm to DotNetOpenAuth's OpenIdRelyingParty.CreateRequest method, DotNetOpenAuth simply uses the current web application root URL. This is a reasonable default, except that if your site is accessible in more than one way (e.g. http and https, or with and without the www. host name) than the default realm will vary based on the URL the user happened to use to reach your login page. And when the realm varies, so do Google's generated claimed identifier.
The fix then, is for you to pick one realm (preferably one with an https scheme if that's an option) and explicitly supply it to the CreateRequest method. You must also ensure that your return_to argument to the same method shares a common root with the realm you've chosen. For example, if the realm you choose is:
https://www.mysite.com/
Then you must ensure that your return_to is based on that. Something like:
https://www.mysite.com/login.aspx
If the user has browsed to http://mysite.com/login.aspx, that would be the default URL for the return_to, which would not match the realm you've chosen.
So altogether, it may look like this:
var request = relyingParty.CreateRequest(
"https://www.google.com/accounts/o8/id",
"https://www.mysite.com/",
new Uri("https://www.mysite.com/login.aspx"));
Note that your return_to does not need to be exactly the same with each request as the realm does. So you could have several login page URLs and each one specify its own URL as the return_to parameter. But all return_to URLs must be based on the realm URL.
With that change consistently applied to everywhere you allow users to log in, you should see consistent claimed identifiers from google. Unfortunately, the claimed identifiers you have already obtained using other realms won't match the ones you'll get after this fix. If you need to merge these user accounts, and if you have email addresses for the users you might try merging based on that. But be very wary of this step. It can only be safely done if you're sure the email addresses you have on file belong to those users. If you obtained those email addresses via OpenID when the users logged in, and double checked that it was from an OpenID Provider you trust and that verifies emails, then you're probably OK. Note that just hard-coding Google OP Identifier into CreateRequest does not guarantee that only Google users log in. To make sure of that, you'd have had to be checking that the IAuthenticationResponse.Provider.Uri property matches https://www.google.com/accounts/o8/ud when the positive assertion comes in.

Finding user's groups SIDs inside Sharepoint

I need to find out all AD groups SIDs that current user belongs to inside my Sharepoint (2007) webpart.
I wanted to use System.DirectoryServices.AccountManagement namespace:
using (var context = new PrincipalContext( ContextType.Domain ))
{
using (var user = UserPrincipal.FindByIdentity( context, accountName ))
{
var groups = user.GetAuthorizationGroups();
...
}
}
, but I get the following error:
Event ID: 10016
Through the permission settings (application specific) is the SID (S-1-5-20) for user NT AUTHORITY \ NETWORK SERVICE of address localhost (Using LRPC) is not authorized to activate (Local) for the COM Server application with CLSID
{61738644-F196-11D0-9953-00C04FD919C1}
This might be fixed with this http://support.microsoft.com/kb/899965
but this approach requires changing registry values (the ownership of the application, so you can change apps values at dcomcnfg) and later User Permissions at dcomcnfg's COM security, which isn't an option for me.
Is there another way to access Current user's groups SIDs inside Sharepoint?
I really hoped I can find these values in SPContext.Current.Web.CurrentUser.Groups, but apparently not.
You need to go the SharePoint way here and not use System assemblies, but the SharePoint ones.
The SID of each user is in the SPUser.Sid Property. As you want to look for AD groups only you can check the .IsDomainGroup Property of SPUser.
Now all you need to do is check the current user: ´SPContext.Current.Web.CurrentUser(aSPUser` object).
To answer your question how to get all groups a user belongs to, you actually will need to use System.DirectoryServices. A solution for your problem is shown in the following stackoverflow posts:
In C#, how to access Active Directory to get the list of groups that a certain user belongs to?
Querying AD for finding all groups of a user - Missing one group
So in short: SPUser object as well as querying the Active Directory via DirectoryServices

MVC Active Directory Membership

I am trying to make use of the active directory membership rather than SQL but there is very limited documentation available online. I have managed to connect my application to the domain controller without any problems but when you use "Context.User.Identity.Name" it comes up with DOMAIN\User. I want to basically drill down and get information such as full name, e-mail address, etc.
I just need a useful link and the searching I have done doesn't appear to have got me anywhere!
Many thanks
This should give you a bit of a clue: http://msdn.microsoft.com/en-us/library/ms973834.aspx
and here is a list of LDAP properties that you might want to play around with in the search result: http://www.computerperformance.co.uk/Logon/LDAP_attributes_active_directory.htm
Have you tried with this doc?
http://msdn.microsoft.com/en-US/library/system.web.security.activedirectorymembershipprovider%28v=vs.90%29.aspx
Can help?
If you are making use of Active Directory then you are likely using Windows Authentication. If so, all you need to do is:
Reference System.DirectoryServices.AccountManagement
In code (perhaps a controller action or model constructor)
// establishes your domain as the context for your user lookup
var principalContext = new PrincipalContext(ContextType.Domain, "domainName");
// gets the current user's UserPrincipal object
var userPrincipal.FindByIdentity(principalContext, #User.Identity.Name)
// example
var email = userPrincipal.EmailAddress;
Note:
This works because Windows Authentication means User.Identity on the current HttpContext is a WindowsIdentity and thus its Name property can be used to search AD.
You aren't limited to looking up the current user. You can use FindByIdentity() to search any value passed, and this method exists on other principals (ex. GroupPrincipal). You can also designate you wish to search by another type such as SID instead of Name.
Enjoy!

Categories