Reputation: 89
In .NET 8, I have a function to check if the user belongs to a local group in order to authorize controllers and methods:
public static bool IsUserInLocalGroup(string userName, string groupName)
{
using (PrincipalContext pc = new PrincipalContext(ContextType.Machine))
{
using (GroupPrincipal group = GroupPrincipal.FindByIdentity(pc, groupName))
{
if (group != null)
{
return group.GetMembers(true).Any(m => m.SamAccountName.Equals(userName, StringComparison.OrdinalIgnoreCase));
}
}
}
return false;
}
It works fine in debug mode, but once published to the production IIS, it fails with an error
The network path was not found
I think the user that runs the app in IIS does not have permission to check local groups, so I changed the identity from ApplicationPoolIdentity
to LocalSystem
, but it still doesn't work.
Is there anything else I need to do? Any help to solve this issue will be appreciated.
Edit: I call this function from program.cs like this:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("Admin", policy =>
policy.RequireAssertion(context =>
{
try
{
var userName = context.User.Identity?.Name?.Split('\\').Last();
return LocalGroupHelper.IsUserInLocalGroup(userName, "rWork-Admin");
}
catch (Exception ex)
{
Console.WriteLine($"[ERROR]: {ex.Message} \n {ex.StackTrace}");
File.AppendAllText("logs/error_log.txt", $"[{DateTime.Now}] {ex.Message} \n {ex.StackTrace}\n");
return false;
}
}));
});
Then, I authorize my controllers and methods with [Authorize(Policy = "Admin")]
Upvotes: 0
Views: 30
Reputation: 89
I will answer myself because I solved the issue by changing the approach. I still don't know why it fails using System.DirectoryServices.AccountManagement
, but I realized that when using DirectoryEntry
it works good in both server and development sides. So permissions and IIS configuration are good. Here is my finally method:
public static bool IsUserInLocalGroup(string userName, string domain, string groupName)
{
string userPath = $"WinNT://{domain}/{userName}";
try
{
using (var group = new DirectoryEntry($"WinNT://{Environment.MachineName}/{groupName},group"))
{
foreach (var member in (IEnumerable)group.Invoke("Members"))
{
using (var memberEntry = new DirectoryEntry(member))
{
if (memberEntry.Path.Equals(userPath, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"[ERROR]: {ex.Message} \n {ex.StackTrace}");
File.AppendAllText("logs/error_log.txt", $"[{DateTime.Now}] {ex.Message} \n {ex.StackTrace}\n");
return false;
}
return false;
}
Upvotes: 0