0

Looking for some guidance on how to best solve this problem: I have a dot net core 2.2 website project that is basically a container of links to other single page MVC sites (within the same domain) that, when these 'child' apps are requested (clicked), will display within the content window of my parent application. When the parent app is initially loading the AD authentication will occur, and the list of authorized site links will be loaded from a database based on the users's AD security groups/roles. When the user clicks on a child app link, the child app's controller will have an authorize attribute just to further secure it in the event the child app's URL is known. I'd like to have the parent application handle all logging, despite the child apps doing all the heavy lifting for their specific task.

Some Questions/More detail:

  • Displaying the child sites in a parent div? Should i use iframes? Something else, different design?
  • Parent site security? I have the AD functionality already handled and can grab the specific security groups, but should I use a cookie, token, something else? Not sure where the windows auth token gets stored though...
  • Child site security? Requesting the child site is basically a GET request, but how should I secure this, and implement the role based Authorize? How to pass in the parent auth token into the child's Get request?
  • Parent application handling Child logging: I need a simple method to implement logging within the child apps, but ideally it talks to the parent to handle all this. One point of contact for all child--> parent communication, with very little setup/configuration in the child. When the child app does its specific task, I want to have something like log.Info("My Message") as if it was locally configured with nlog or serilog. When logging needs to happen, it's the child app's controller where the processing will be happening. I found this link which seems interesting where the Child site posts to a method which starts a task, and another post that checks updates. call-back-from-server-to-client. How can I get from the Child's controller back to the parent?

Lots of questions, and I appreciate your help on this. Thank you!

RichieMN
  • 905
  • 1
  • 12
  • 33
  • 1
    I use 'iframe' to load child pages into my parent page as a modal popup. I can exchange values between pages with very little trouble. Only 1 'iframe' is needed and you can load multiple child pages within the parent page. This only works if the child pages are of the same domain as the parent page. – CharlesEF Sep 01 '19 at 22:04

1 Answers1

0

In a nutshell, I created my parent application to trigger a GET request and use the site's response to populate a DIV on the parent app. jQuery/Javascript handles this easily. Each child site was setup as a separate site within IIS.

Security was handled using a non identity version of cookie authentication. Microsoft has a nice document here: Use cookie authentication without ASP.NET Core Identity. After a username/password was initially entered, I looked up the user within AD to authenticate.
Some code here (add System.DirectoryServices.AccountManagement):

var context = new PrincipalContext(ContextType.Domain);
                var principal = new UserPrincipal(context, userName, password, true);

                if (context != null)
                {
                    var identityName = name;  // when windows authentication is checked
                    principal = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, name);

                    if (principal != null)
                    {
                        // retrieves security groups
                        var groups = principal.GetGroups(); // security groups

                        var adUser = AdUser.CastToAdUser(principal); // extension method

                        // adds groups to collection
                        adUser.SecurityGroups = groups.Select(x => x.ToAdUserSecurityGroups()); // extension method

                        return adUser;
                    }
                }

Authentication cookies were shared across parent-child using DataProtection, which uses a shared key file. After a successful authentication, the user had their authorized roles (claims) added to the cookie. These authorization roles are accessible from the child app using the following code (exists in both parent/child Startup ConfigureServices):

        var keyPath = Configuration.GetValue(typeof(string), "DataProtection:KeyLocation").ToString();

        services.AddDataProtection()
            .PersistKeysToFileSystem(new DirectoryInfo(keyPath))                
            //.ProtectKeysWithCertificate("{CERTIFICATE THUMBPRINT}")
            .SetApplicationName("My-App-Name");

        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
           .AddCookie(options =>
           {
               options.LoginPath = "/Account/login";
               options.AccessDeniedPath = "/Account/accessdenied";
               options.Cookie.SameSite = SameSiteMode.None;
               options.Cookie.SecurePolicy = CookieSecurePolicy.None;
               options.Cookie.Name = "My-Super-Cool-Cookie-Name";
           });

The child App methods/classes are protected by Authorize attributes like this:[Microsoft.AspNetCore.Authorization.Authorize(Roles ="MySuperSecureRole")]

The 'single-point' logging was handled by creating a Logging Provider project and creating a Logging API (using Serilog). The Provider project, which has been added to all parent/child app solutions, exposes the logging methods, and posts to the Logging API. I found this helpful: Call a Web API From a .NET Client.

Hope this helps!

RichieMN
  • 905
  • 1
  • 12
  • 33