2

I'm trying to implement multi tenancy based on the first folder segment of the request url. In order to isolate cookies between the tenants I'm trying to configure them with different names but I'm having a hard time figuring out how to do it. Currently my code is like this:

foreach (SiteFolder f in allFolders)
{
    PathString path = new PathString("/" + f.FolderName);
    app.Map(path,
    siteApp =>
    {

    // this commented line would normally configure the cookies but I'm trying to do it myself below
    //siteApp.UseIdentity();

        siteApp.UseCookieAuthentication(options =>
        {
            options.LoginPath = new PathString("/" + f.FolderName + "/Account/Login");
            options.LogoutPath = new PathString("/" + f.FolderName + "/Account/LogOff");
            options.CookieName = f.FolderName + "-ext";
            options.SlidingExpiration = true;
        },
        IdentityOptions.ExternalCookieAuthenticationScheme
        );

        siteApp.UseCookieAuthentication(options =>
        {
            options.LoginPath = new PathString("/" + f.FolderName + "/Account/Login");
           options.LogoutPath = new PathString("/" + f.FolderName + "/Account/LogOff");
            options.CookieName = f.FolderName + "-tfr";
            options.SlidingExpiration = true;
        },
        IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme
        );

        siteApp.UseCookieAuthentication(options =>
        {
            options.LoginPath = new PathString("/" + f.FolderName + "/Account/Login");
            options.LogoutPath = new PathString("/" + f.FolderName + "/Account/LogOff");
            options.CookieName = f.FolderName + "-tf";
            options.SlidingExpiration = true;
        },
        IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme
        );

        siteApp.UseCookieAuthentication(options =>
        {
            options.LoginPath = new PathString("/" + f.FolderName + "/Account/Login");
            options.LogoutPath = new PathString("/" + f.FolderName + "/Account/LogOff");
            options.CookieName = f.FolderName + "-app";
            options.SlidingExpiration = true;
        },
        IdentityOptions.ApplicationCookieAuthenticationScheme
        );

    });
}

but none of the options including the cookie name I'm changing seem to have any effect.

I'm also a little confused because some things in Identity get "configured" by dependency injection rather than by IApplicationBuilder. I would expect that things previously configured by DI would be just defaults thaT could be changed later by IApplicationBuilder but it isn't clear to me how.

Can anyone shed any light on how to alter things such as cookie name when using Identity?

Joe Audette
  • 35,330
  • 11
  • 106
  • 99
  • It should work. Isn't your issue related to your other one, with `app.Map`? – Kévin Chalet Jul 25 '15 at 23:19
  • Curious: did you try using the `app.UseWhen` extension to configure your authentication middleware? – Kévin Chalet Jul 26 '15 at 16:56
  • I'm still using app.Map at the moment but intend to try app.UseWhen soon to see what the differences will be. update to my question I "thought" it wasn't working because if I log in to the root level site I'm also logged into the folder site. but if I don't login to the root site and only login to the folder site then I am not logged into root so folder site is clearly using the different cookie name. but I'm still researching because my desire is that login to root site does not also appear as logged in to folder child site. – Joe Audette Jul 26 '15 at 17:04
  • You could set `CookieAuthenticationOptions.CookiePath` but it wouldn't satisfy your last requirement, since an authentication cookie issue for /vdir would also work for /vdir/sitefolder1 and /vdir/sitefolder2. Using conditional middleware execution with `app.UseWhen` should work. Using different cookie names for both the root site and the site folders should be enough to make sure the cookie middleware defined at the root level is never called when making a call to a site folder. – Kévin Chalet Jul 26 '15 at 17:34
  • You should also use unique **authentication schemes** to make sure a bad guy can't rename cookies and use them on other site folders: the scheme value directly controls the identifiers used by the data protector to protect the cookie. Using different schemes will result in different data protectors, being unable to read each others' cookies. – Kévin Chalet Jul 26 '15 at 17:36
  • I've tried now with both app.Map and app.UseWhen. My finding is if I use app.Map and I login to a folder site I am not logged into the root site but logging into the root site is also logged into child folder site. If I try to change the cookie path for the folder sites it has opposite effect of expected, login to child site now is also logged into root site. in the case of app.UseWhen logging into the child folder site also logs into the root site regardless of cookie name or path. so not having luck with my goals. – Joe Audette Jul 26 '15 at 19:36
  • wonder if it is a similar problem as with previous versions of Identity http://stackoverflow.com/questions/29518092/variable-cookie-path-with-asp-net-identity but I can't figure how to implement the previous solution since so much has changed – Joe Audette Jul 26 '15 at 19:38
  • You should update your question with the current bits, including both the root configuration and the sites configurations. – Kévin Chalet Jul 26 '15 at 19:41
  • which version should I post app.UseWhen or app.Map? Maybe I could email you my startup file? – Joe Audette Jul 26 '15 at 19:44
  • both versions are basically identical with what I already posted other than app.Map vs app.UseWhen I tried moving the main site cookie config before and after but I guess it always runs first since the app.UseWhen only fires as true if the request comes in for the folder site – Joe Audette Jul 26 '15 at 19:51
  • you mentioned about AuthenticationScheme but don't I have to use IdentityOptions.ApplicationCookieAuthenticationScheme and the others as shown above for it to work with Identity, I'm configuring multiple cookies and the only thing different between them is the authentication scheme, is that not what aligns each cookie with its purpose? I don't really understand how authenticationscheme works maybe those are not really letting me change the cookie names? – Joe Audette Jul 26 '15 at 19:59
  • You should upload both versions on GitHub or on GitHub Gist. Concerning Identity, I was pretty sure you could configure the schemes internally used by the managers on a per-instance basis (using `services.Configure(...)`), but that's not the case and it's a real shame: it's a static property. This will make your multi-tenant scenario a real pain, I'm afraid. At least if you want your implementation to be safe. You should definitely file a ticket on aspnet/Identity, even if I already know the answer... – Kévin Chalet Jul 26 '15 at 20:11
  • An option might be to add a unique claim containing the identifier of the tenant the cookie was issued for, and check it using the cookies middleware notifications or directly in your application (in your controllers for instance), to make sure we can't rename a cookie issued for tenant A and use it for tenant B. – Kévin Chalet Jul 26 '15 at 20:13
  • my code is in a private repo on github, I just synced and added you as a collaborator so you can see it. later this project will become public and open source. startup files are in the WebHost project – Joe Audette Jul 26 '15 at 20:18
  • Sadly, I don't have enough time to cautiously look at such a massive thing, but it sounds like the root authentication middleware are not embedded in a `app.UseWhen` call. Try wrap them in a `app.UseWhen` that would prevent them from being called when trying to reach the root site. – Kévin Chalet Jul 26 '15 at 20:32
  • just tried that but no change in result no matter if I login to root level of child level I'm logged into both. I really appreciate all of your help. From what you've said though now I'm really worried whether I will be able to achieve my project goals. I've been very excited about asp.net 5 thinking it would enable me to do all these things in a clean way because it is supposed to be so flexible and configurable but it isn't really turning out to be that flexible and configurable. – Joe Audette Jul 26 '15 at 20:46
  • Hehe, you can't imagine how much energy I've spent to try influencing some of their design decisions :) Any chance you could merge your last commit so I can take a look? – Kévin Chalet Jul 26 '15 at 20:58
  • just synced it. the main app uses app.When(IsNotSiteFolder and the folder sites are configured via app.UseCloudscribeCoreFolderTenantsv2(config, siteRepo); the same method name without v2 is the alternate version using app.Map but the currently active one v2 uses app.UseWhen(IsFolderMatch – Joe Audette Jul 26 '15 at 21:14
  • just synced again as I saw a mistake but it didn't change anything when I fixed it – Joe Audette Jul 26 '15 at 21:18
  • update on this, with your help I am able to login to the root or the tenant without also being logged into the other one. but the code I'm using to change the cookie name is not working because if I login to root and then login into tenant in another browser tab it logs me out of the other site, so each site is overwriting the other site cookie – Joe Audette Jul 27 '15 at 20:11
  • 1
    I finally managed to implement custom cookieauthentication schemes per site and different cookie names per site. I had to implement a custom SignInManager and custom ClaimsPrincipalFactory to get at all the points where authscheme needed adjusting. The problem is now I have to wire up cookies in DI for each site and branch the cookie middleware for each site which is not going to scale well to lots of sites. seems like I need one custom cookie middleware to handle all sites instead but hat to have to implement that myself. wish the framework could be more supportive of multi tenancy – Joe Audette Jul 31 '15 at 19:39
  • I encourage anyone else reading this if you want the framework to better support multi tenancy please add your support on this issue https://github.com/aspnet/Security/issues/35 maybe if enough people show interest they will make it better – Joe Audette Jul 31 '15 at 19:44
  • I think this answer could help you http://stackoverflow.com/questions/22989920/asp-net-identity-setting-cookiedomain-at-runtime – Danilow Jan 06 '17 at 15:56

0 Answers0