2017-08-03 2 views
0

Ich eingerichtet Multitenancy für meine ASP.NET MVC-Projekt mit Standard-ASP.Net Identitäts-Cookie-Authentifizierung. Daher habe ich den Hauptmandanten (normaler Mandant plus Zugriff auf einige Mandanten-Admin-Tools), der auf mysite.com erreichbar ist, und verschiedene Mandanten auf t1.mysite.com, t2.mysite.com.ASP.NET Identity Multitenant Login-Problem

Ein Login auf t1.mysite.com ist nicht gültig auf t2.mysite.com, was genau das ist, was ich möchte. Wenn ich mich jedoch auf mysite.com anmelde, dann habe ich, während ich mich eingeloggt habe, auf tX.mysite.com zugegriffen, als ob ich noch angemeldet bin. Obwohl die Identität der Anwendung, die ich habe, nicht existiert.

Gibt es eine Möglichkeit, sicherzustellen, dass der für mysite.com erhaltene Authentifizierungscookie auf tX.mysite.com nicht gültig ist, sodass Administratoren nicht versehentlich in einem nicht funktionierenden Mandanten landen können (die GUI ist sichtbar, aber Sie kann nichts tun, da mysite.com das Login für nicht gültig auf tx.mysite.com ist so ist es am besten, nur den Login-Bildschirm anzuzeigen)

Antwort

0

In Ihrer App_Start\Startup.Auth.cs Datei sollten Sie etwas über OnValidateIdentity haben:

app.UseCookieAuthentication(new CookieAuthenticationOptions 
{ 
    Provider = new CookieAuthenticationProvider 
    { 
     OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<Infrastructure.Identity.UserManager, ApplicationUser>(
      validateInterval: TimeSpan.FromMinutes(30), 
      regenerateIdentity: (manager, user) => manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie)) 
    }, 
    // Other stuff 
});   

Siehe diesen Parameter validateInterval - standardmäßig ist es auf 30 Minuten eingestellt. So oft wird der Cookie tatsächlich mit den Werten in der Datenbank verglichen.

Ändern Sie den Wert auf TimeSpan.FromSeconds(30). Dies vergleicht den Cookie mit dem Wert in der Datenbank alle 30 Sekunden und wenn die Identität für den Mandanten nicht gültig ist, wird dem Benutzer ein Login-Portal angezeigt.

Sie können es auch in 0 ändern, aber ich denke, dass wird Ihre Datenbank überlasten - auf jede Anfrage wird es ein paar Anrufe an die DB.

Auch gibt es eine Eigenschaft CookieDomain Eigenschaft auf CookieauthenticationOptions:

app.UseCookieAuthentication(new CookieAuthenticationOptions 
{ 
    // other stuff 
    CookieDomain = "example.com" 
}); 

Dies könnte Ihnen helfen, aber weil dieses Element so früh in der Pipeline so konfiguriert ist, kann es schwierig sein, während der Laufzeit neu zu konfigurieren.

Eine weitere Option ist es, mehrere Cookie authenticaion Middle haben, aber das wird nur funktionieren, wenn die Anzahl der Mieter bekannt ist und sehr begrenzt:

app.UseCookieAuthentication(new CookieAuthenticationOptions 
{ 
    // other stuff 
    AuthenticationType = "myTenant1", 
    CookieDomain = "t1.example.com" 
}); 

app.UseCookieAuthentication(new CookieAuthenticationOptions 
{ 
    // other stuff 
    AuthenticationType = "myTenant2", 
    CookieDomain = "t2.example.com" 
}); 

aber dies könnte Ihnen mehr Kopfschmerzen als es eigentlich wert ist.

+0

Hmm, ich schätze, das würde den Benutzer nach 30 Sekunden auf die richtige Anmeldeseite umleiten, was besser ist als nichts, aber immer noch nicht so direkt, wie ich es wollte. Da mein Datenspeicher "remote" ist, möchte ich die Anzahl der Anfragen gering halten. Also, gibt es nicht eine Möglichkeit, nur auf den Autorisierungs-Cookie zu schauen, Domains zu vergleichen, und wenn es nur eine teilweise Übereinstimmung ist, unautorisiert zurückzugeben. Ich arbeite gerade mit einem benutzerdefinierten CookieAuthenticationProvider, aber ich bin noch nicht dort angekommen - und ich vermute, dass dies die gleiche Einschränkung haben kann. – user3566056

+0

@ user3566056 aktualisiert meine Antwort – trailmax

0

Also habe ich einen anderen Weg gefunden, um mit dem Problem umzugehen. Es scheint, dass ich direkt in die Cookie-Authentifizierung einhaken kann und die Identität einfach zurückweisen kann, wenn sie vom falschen Mieter stammt.

Also schrieb ich meine benutzerdefinierte CookieAuthenticationProvider

public class TenantCookieAuthenticationProvider: CookieAuthenticationProvider 
{ 

    public override Task ValidateIdentity(CookieValidateIdentityContext context) 
    { 
     string tenantId = SubdomainRoute.GetSubdomain(context.Request.Host.Value); 
     if (!string.IsNullOrEmpty(tenantId)) // we're trying to access mysite.com from x.mysite.com 
     { 
      context.RejectIdentity(); 
      return Task.FromResult<int>(0); 
     } 
     return base.ValidateIdentity(context); 
    } 
} 

und in die Authentifizierungs-Pipeline Haken in Startup.cs

app.UseCookieAuthentication(new CookieAuthenticationOptions 
     { 
      AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 
      LoginPath = new PathString("/Account/Login"), 
      Provider = new TenantCookieAuthenticationProvider 
      { 
       // Enables the application to validate the security stamp when the user logs in. 
       // This is a security feature which is used when you change a password or add an external login to your account. 
       OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
        validateInterval: TimeSpan.FromMinutes(30), 
        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) 
      } 
     }); 

Natürlich, das ist nur die Hälfte der Schlacht .. die andere Hälfte ist nicht die Identität zurückweisen, falls es ein gültiger Mieterbenutzer ist. Da ich die mandantId beim Erstellen der Benutzer als Anspruch hinzufüge, kann ich diese Ansprüche extrahieren und vergleichen, um gültige Mandantenbenutzer nicht abzulehnen.So angepasst I ValidateIdentity wie folgt

public override Task ValidateIdentity(CookieValidateIdentityContext context) 
    { 
     System.Security.Claims.Claim tenantClaim = context.Identity.Claims.FirstOrDefault(x => x.Subject.Name == "tenant"); 
     string tenantId = SubdomainRoute.GetSubdomain(context.Request.Host.Value); 
     if (tenantClaim != null) 
     { 
      if (tenantId != tenantClaim.Value) 
      { 
       context.RejectIdentity(); 
       return Task.FromResult<int>(0); 
      } 
     } 
     else 
     { 
      if (!string.IsNullOrEmpty(tenantId)) // we're trying to access audm.local from x.audm.local 
      { 
       context.RejectIdentity(); 
        return Task.FromResult<int>(0); 
      } 
     } 
     return base.ValidateIdentity(context); 
    } 

Und jetzt habe ich sogar eine zusätzliche Ebene der Sicherheit, so dass Benutzer „Hop zwischen Mietern“ nicht.