WindowsIdentity - Difference between Groups and Claims - c#

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.

Related

Does .IsInRole work for SIDS in the sidhistory attribute?

We are migrating to another network and are trying to prepare our code base. Our existing groups and members will be imported to new groups on our new domain, and the existing group SID will be in the SID history of the newly created groups.
We currently use IsInRole to check user membership in groups. Does this method also check the SID history attribute? We have no way of populating the SID History attribute ourselves to test this.
The source code for IsInRole is available. Lines 166 to 169 show how it works:
// CheckTokenMembership will check if the SID is both present and enabled in the access token.
if (!Interop.Advapi32.CheckTokenMembership((_identity.ImpersonationLevel != TokenImpersonationLevel.None ? _identity.AccessToken : token),
sid.BinaryForm,
ref isMember))
This looks for the group's SID in the access token of the user. The token is created when the user is authenticated and includes the SIDs of all security (not distribution) groups (and nested groups) that the user is a member of.
The documentation Using SID History to Preserve Resource Access says:
After migrating an account and maintaining the SID history of the source domain account, when a user logs on to the target domain, both the new SID and the original SID from the SID history attribute are added to the access token of the user and determine the local group memberships of the user. The SIDs of the groups in which the user is a member are then added to the access token, together with the SID history of those groups.
So that sounds like the SID history of both the user and the group are used when building the access token.

Adding guest user to Azure AD group fails with correct permissions set

I'm inviting users to my org through my web app and adding them to groups which will be used to determine which parts of the web app they can use because I've got the groups associated with my different roles.
The invite to the org goes out fine, but when I attempt to add the user to the group, I get a Microsoft.Graph.ServiceException as follows:
'Code: Authorization_RequestDenied
Message: Insufficient privileges to complete the operation.
Insufficient privileges seems different from the application permissions I've got with admin consent granted on the app registration:
Directory.ReadWrite.All, and
GroupMember.ReadWrite.All
For the life of me I can't find anything relating to "privileges" in the azure portal as it would involve group management so I have to assume that permissions is what this refers to; only, I don't know what permissions it's looking for in addition to these two.
Per the permissions indicated on MS Docs article on adding members to groups, I'm initializing MS Graph with the permissions:
var initialScopes = new string[]
{
// Directory.ReadWrite.All
Constants.Graph.DirectoryReadWrite,
// GroupMember.ReadWrite.All
Constants.Graph.GroupMemberReadWrite,
// Group.ReadWrite.All
Constants.Graph.GroupReadWrite,
// RoleManagement.ReadWrite.Directory
Constants.Graph.RoleManagementReadWriteDirectory
};
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
// Redacted for brevity
})
.EnableTokenAcquisitionToCallDownstreamApi(options =>
configuration.Bind("AzureAd", options), initialScopes)
.AddMicrosoftGraph(configuration.GetSection("GraphAPI"))
GraphAPI section of my config looks like this:
"GraphAPI": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "GroupMember.ReadWrite.All Group.ReadWrite.All Directory.ReadWrite.All RoleManagement.ReadWrite.Directory"
},
I can't possibly be missing any of the required permissions (indicated per the doc). I've logged out and back in again several times (and also completely cleared all my browsing data for the site) to refresh the token auth token but still no luck.
My code to add the invited user to the groups:
// Determine the ID of the regional group to which the user should be added.
string region = this.Provider.Region switch
{
Region.Redacted => config["Groups:redacted"],
Region.Redacted => config["Groups:redacted"],
_ => config["Groups:redacted"]
};
// Add the user to the regional group and to the group for the user's intended role.
var groups = new List<string>
{
region,
config["Groups:redacted"]
};
foreach (var group in groups)
{
await graphClient.Groups[group].Members.References
.Request()
.AddAsync(directoryObject);
}
Are there any additional permissions I need here? If not, what does the error actual indicate is the problem and how do I correct it?
Given the delegated permissions you're requesting (which should cover all scenarios, including role-assignable groups), the most likely cause for this is that the signed-in user is not authorized to manage the membership of the group in question.
In general, whether a user is allowed to manage a group's membership depends on the type of group, and whether the user is owner of the group or not:
Owned groups:
All member users
Security groups, not role-assignable groups:
Intune Administrator
Knowledge Administrator
Knowledge Manager
Windows 365 Administrator
Microsoft 365 groups, not role-assignable groups:
Exchange Administrator
SharePoint Administrator
Teams Administrator
Security groups and Microsoft 365 groups, not role-assignable groups:
User Administrator
Groups Administrator
Identity Governance Administrator can manage
Role-assignable groups, not security groups nor Microsoft 365 groups:
Privileged Role Administrator
All groups, including role-assignable groups
Global Administrator
(This information is essentially a pivot on what's listed here: https://learn.microsoft.com/en-us/azure/active-directory/roles/permissions-reference, which can also be retrieved from Microsoft Graph by querying GET .../roleManagement/directory/roleDefinitions.)

How can I securely ensure the current user belongs to an Active Directory Group?

I am creating a C# Winform Application which will be used in a corporate domain (Windows Active Directory). The app is to behave as the following:
When a user opens the App, the App checks if the current user is part of an Active Directory group.
If it is, the app then allows the user to use the app.
From google searches, I found several ways how to check if a user is part of an Active Directory group.
For example in the link here => How to check if a user belongs to an AD group?
My concern is the security part of this. What if someone spoofs a username and domain. He won't need to know the password to allow access to the app.
Don't do a look up. The SID of every group the user is a member of (recursively) is part of the user's login token. So you can just use WindowsPrincipal.IsInRole(). If you only have the name of the group, you can give it that:
var currentUser = new WindowsPrincipal(WindowsIdentity.GetCurrent());
currentUser.IsInRole("SomeGroup")
That translates the name into the SID and checks the login token for that SID. That requires a network request. If you can give it the SID of the group instead, then you can save that network request:
var groupSid = new SecurityIdentifier("S-1-5-21-blah");
currentUser.IsInRole(groupSid)

UserPrincipal.GetGroups vs. UserPrincipal.GetAuthorizationGroups?

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.

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

Categories