0

I would like to selectively display a block of text on a page depending on which AD-Group a user is in. The page is a simple list of links ATM, no controller necessary. I have the code below which works perfectly when I am developing locally (I am logged onto the AD) - as soon I publish the application to an IIS server I get a 404 error - I have been able to locate the exact line that is causing the error -> in ActiveDirectory.IsInGroup () the line group.Translate is the culprit.

I have checked the Event Viewer on the IIS Server (and the log for IIS) but nothing is being logged at all?

This is the index.html:

@page
@using System.Security.Principal
@{
    ViewData["Title"] = "Landing Page";
}

@{    
   var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
   bool itUser = ActiveDirectory.IsInGroup(principal, "IT Department");
}

<h4>Header</h4>

@if (itUser || adminUser)
    {
       <div class="card mb-4 shadow-sm">
          <div class="card-header">
             <h4 class="my-0 font-weight-normal">IT</h4>
          </div>
          <div class="card-body">
             <a target="_blank" href="http://www.test.com/Configuration/Index" class="btn btn-secondary my-2">Application Config</a><br />
          </div>
       </div>
    }

here is the C# code:

public static class ActiveDirectory

       public static bool IsInGroup(ClaimsPrincipal checkUser, string checkGroupName)
    {
        var identity = (WindowsIdentity)checkUser.Identity;
        if (identity?.Groups == null) return false;

        foreach (var group in identity.Groups)
        {
            var groupName = group.Translate(typeof(NTAccount)).ToString(); // this gives me a 404 error
            if (groupName.ToLower().Contains(checkGroupName.ToLower())) return true;
        }

        return false;
    }
}
Ursus Schneider
  • 447
  • 1
  • 6
  • 22
  • Questions: Is the server joined in the same domain that your development machine? Is the web application configured to use windows authentication and impersonation? If not, I think the sentence WindowsIdentity.GetCurrent() will get the user running the application pool in IIS, that can be a local machine user, other user in the domain, etc. – Pepelui360 Feb 19 '20 at 15:28
  • Also, see this thread in asp.net forums: https://forums.asp.net/t/1817037.aspx?Windows+Authentication+with+Impersonation. IIS on the server and IIS Express on your development machine are two very different animals. – Pepelui360 Feb 19 '20 at 15:32
  • Yes, the server and my development machine are on the same domain. Yes, the web application is configured to use windows auth. Even so, if I got the wrong user I would be fine with it - I am getting a 404 page... nothing in the logs (neither IIS nor Windows event log) - that is the thing that is weird for me? – Ursus Schneider Feb 20 '20 at 15:48

1 Answers1

1

Not utilizing a controller is bad practice (and defeats the purpose of utilizing MVC Framework (Model View Controller)), especially with concern to establishing auditability and authentication/authorization checks.

Best practice would be to have your default ActionResult (which is set in your RouteConfig file) on your controller call a function that you define to get a list of which groups your end user is a part of

Example:

Pass in the following in each controller ActionResult:

// what will be needed:    
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;



var userSignOn = System.Web.HttpContext.Current.Request.LogonUserIdentity.Name;

List<string> activedirectoryGroupList = new List<string>();

activedirectoryGroupList = GetGroupsFromSignOn(userSignOn);

The function being called:

internal static List<string> GetGroupsFromSignOn(string signOn)
{
    string searchText = "(&(objectCategory=person)(objectClass=user)(sAMAccountName={0}))";
    searchText = searchText.Replace("{0}", signOn);

    Domain domain = Domain.GetCurrentDomain();
    DirectoryEntry userEntry = domain.GetDirectoryEntry();

    DirectorySearcher searcher = new DirectorySearcher(userEntry, searchText);
    SearchResult result = searcher.FindOne();

    DirectoryEntry currentUserEntry = result.GetDirectoryEntry();

    List<string> activedirectoryGroupList = new List<string>();

    if (currentUserEntry != null)
    {           
        int propertyCount = currentUserEntry.Properties["memberOf"].Count;

        string activedirectoryGroup;

        for (int i = 0; i < propertyCount; i++)
        {
            activedirectoryGroup = Convert.ToString(currentUserEntry.Properties["memberOf"][i]);

            int startIndex = activedirectoryGroup.IndexOf('=');
            startIndex += 1;

            int endIndex = activedirectoryGroup.IndexOf(',');

            int stringLength = endIndex - startIndex;

            activedirectoryGroup = activedirectoryGroup.Substring(startIndex, stringLength);

            activedirectoryGroupList.Add(activedirectoryGroup);
        }

        return activedirectoryGroupList;
    }
    else
    {
        return null;
    }
}

From there, you would have a list of the AD Groups your user would be a part of, and you can either cross reference these groups with your authorized group name(s) that you can set either in your web config file, or in a SQL database that you can call out to.

As for determining what would be displayed, you should likely set up a master view, with partial views rendered on that page depending upon your user's authorization status for that information.

Edit:

Useful thread about the challenges of authentication with asp.net MVC

C Murphy
  • 47
  • 1
  • 13
  • Thank you very much for your response. I would normally go the whole 9 yards with this (MVC etc.) but... it is really just a single page that presents the user with a list of links - just like a start page of sorts. There is no model to speak of (no data to pass at all) - just a single page. I wanted a way to hide links if you are not in a specific group. I have the code, it just doesn't work on an IIS server (newest version, all patched up). What I do not understand is WHY the code causes a 404 error? – Ursus Schneider Feb 20 '20 at 16:10
  • Since I have never tried performing authorization checks directly in the view, the only suggestion I have would be to throw a display object for the "user" so that way you can see, when your page is deployed on the server, that it is correctly identifying the windows user for your AD Group check. – C Murphy Feb 20 '20 at 16:26
  • I am not having the problem that the user is being incorrectly identified - I do not get there ATM. I am getting a 404 error on the line: var groupName = group.Translate(typeof(NTAccount)).ToString(); – Ursus Schneider Feb 20 '20 at 16:41
  • to quote back to @Pepelui360, "WindowsIdentity.GetCurrent() will get the user running the application pool in IIS" (as in not the windows user for your app). If that is true, it will not find the IIS user in Active Directory and fail to render the view. – C Murphy Feb 20 '20 at 16:47
  • Thank you again, I do get that, but that is not the problem ATM. Any idea WHY I could be getting a 404? – Ursus Schneider Feb 20 '20 at 17:05