2016-06-20 28 views
3

Ich habe eine mandantenfähige Anwendung, in der jeder Mandant seine eigenen MetaData URl, ClientId, Authority usw. für WsFed oder OpenIdConnect (Azure) oder Shibboleth (Kentor) definieren kann. Alle Mieter sind in DB-Tabelle gespeichert und registriert in der OwinStartup wie folgt:Multi-Tenant-Authentifizierung mit OWIN-Pipeline

 // Configure the db context, user manager and signin manager to use a single instance per request 
     app.CreatePerOwinContext(ApplicationDbContext.Create); 
     app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); 
     app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create); 

     // Enable the application to use a cookie to store information for the signed in user 
     // and to use a cookie to temporarily store information about a user logging in with a third party login provider 
     // Configure the sign in cookie 

     app.UseCookieAuthentication(new CookieAuthenticationOptions 
     { 
      AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 
      // CookieName = "Kuder.SSO", 
      LoginPath = new PathString("/Account/Login-register"), 
      Provider = new CookieAuthenticationProvider 
      { 
       //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)) 
      } 
     }); 

     app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); 

    OrganizationModel objOrg = new OrganizationModel(); 
    var orgList = objOrg.GetOrganizationList(); 
    foreach (OrganizationModel org in orgList) 
    { 
     switch (org.AuthenticationName) 
     { 
      case "ADFS": 
      WsFederationAuthenticationOptions objAdfs = null; 
      objAdfs = new WsFederationAuthenticationOptions 
       { 
        AuthenticationType = org.AuthenticationType, 
        Caption = org.Caption, 
        BackchannelCertificateValidator = null, 
        MetadataAddress = org.MetadataUrl, 
        Wtrealm = org.Realm, 
        SignOutWreply = org.Realm, 
        Notifications = new WsFederationAuthenticationNotifications 
        { 
         AuthenticationFailed = context => 
         { 
          context.HandleResponse(); 
          Logging.Logger.LogAndEmailException(context.Exception); 
          context.Response.Redirect(ConfigurationManager.AppSettings["CustomErrorPath"].ToString() + context.Exception.Message); 
          return Task.FromResult(0); 
         } 
        }, 
        TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false }, 
       }; 
      app.UseWsFederationAuthentication(objAdfs); 
       break; 
      case "Azure": 
       OpenIdConnectAuthenticationOptions azure = null; 
       azure = new OpenIdConnectAuthenticationOptions 
       { 
        AuthenticationType = org.AuthenticationType, 
        Caption = org.Caption, 
        BackchannelCertificateValidator = null, 
        Authority = org.MetadataUrl, 
        ClientId = org.IDPProvider.Trim(), 
        RedirectUri = org.Realm, 
        PostLogoutRedirectUri = org.Realm, 
        Notifications = new OpenIdConnectAuthenticationNotifications 
        { 
         AuthenticationFailed = context => 
         { 
          context.HandleResponse(); 
          Logging.Logger.LogAndEmailException(context.Exception); 
          context.Response.Redirect(ConfigurationManager.AppSettings["CustomErrorPath"].ToString() + context.Exception.Message); 
          return Task.FromResult(0); 
         } 
        }, 
        TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false }, 
       }; 
       app.UseOpenIdConnectAuthentication(azure); 
       break; 
      case "Shibboleth": 
       var english = CultureInfo.GetCultureInfo("en-us"); 
       var organization = new Organization(); 
       organization.Names.Add(new LocalizedName("xxx", english)); 
       organization.DisplayNames.Add(new LocalizedName("xxx Inc.", english)); 
       organization.Urls.Add(new LocalizedUri(new Uri("http://www.aaa.com"), english)); 

       var authServicesOptions = new KentorAuthServicesAuthenticationOptions(false) 
       { 
        SPOptions = new SPOptions 
        { 
         EntityId = new EntityId(org.Realm), 
         ReturnUrl = new Uri(org.Realm), 
         Organization = organization, 
        }, 
        AuthenticationType = org.AuthenticationType, 
        Caption = org.Caption, 
        SignInAsAuthenticationType = "ExternalCookie", 
       }; 
       authServicesOptions.IdentityProviders.Add(new IdentityProvider(
       new EntityId(org.IDPProvider), authServicesOptions.SPOptions) 
       { 
        MetadataLocation = org.MetadataUrl, 
        LoadMetadata = true, 
        SingleLogoutServiceUrl = new Uri(org.Realm), 
       }); 
       app.UseKentorAuthServicesAuthentication(authServicesOptions); 
       break; 
      default: 
       break; 
     } 
    } 

Wenn mehrere orgnaizations von gleichen Provider (ADFS, Azure oder Shibboleth) in Db aktiviert ist, bekomme ich Fehler. Ich habe "app.Map" ausprobiert, um es zu erweitern. Aber nicht erfolgreich. Außerdem verwende ich den unteren Code, um sich für alle Provider (ADFS und Azure) abzumelden, aber das Abmelden schlägt ebenfalls fehl.

Provider ist eindeutig Authentifizierungstyp, den ich in Organisationen verwende.

HttpContext.GetOwinContext().Authentication.SignOut(provider, Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie, DefaultAuthenticationTypes.ExternalCookie); 

Auf der Suche nach Hilfe/Anleitung. Hinweis: Immer, wenn ein neuer Mandant hinzugefügt wird, ist es möglich, appdomain zu recyceln, nicht erforderlich, um die Pipeline dynamisch neu zu erstellen, um die Komplexität zu erhöhen.

Antwort

0

Die Middleware Kentor.AuthServices unterstützt mehrere Instanzen, aber Sie müssen jedem einen spezifischen ModulePath zuweisen. Ohne diese wird die erste Kentor.AuthServices-Middleware alle eingehenden Anfragen behandeln und Fehler auf Nachrichten von IdentityProvidern auslösen, die mit anderen Instanzen konfiguriert sind.

Ich weiß, dass einige der anderen Katana-Provider ähnliche "versteckte" Endpunkte haben, die während des Rückrufs verwendet werden, aber ich weiß nicht, wie sie sich verhalten, wenn mehrere Middleware-Instanzen geladen werden.

Als Alternative unterstützt die Middleware Kentor.AuthServices auch die Verwendung mehrerer Identitätsanbieter, die in einer Instanz registriert sind. Dann können Sie IdentityProvider-Instanzen während der Laufzeit zur KentorAuthServicesAuthenticationOptions hinzufügen und remove und sofort wirksam werden. Dies ist jedoch möglicherweise keine ideale Lösung, wenn Sie eine Middleware pro Mandant für die anderen Protokolle verwenden.

+0

Können Sie einige Schnipsel zeigen, wie Modul Pfad hinzufügen – Saravanan

+0

Es ist eine Eigenschaft in 'SPOptions' –

+0

Für verschiedene Anbieter muss ich entsprechende Berechtigungen hier von IDP bieten? – Saravanan

0

Wäre es nicht möglich sein, verschiedene owin Pipelines pro Mieter erstellen auf der Basis einer Bedingung in app.MapWhen ("tenant1", ctx => ctx.configureSpecificTenant)

MapWhen akzeptiert auch eine Funktion, so könnten Sie Basieren Sie auf einer anderen Bedingung wie einer Sub-Domain mit einer Foreach-Iteration auf einer Liste.

+0

können Sie ein funktionierendes Snippet teilen. Mieter1 kann nur nach URL-Pfad identifiziert werden. h. http: //=/tenant1. Also basierend darauf muss ich die Pipeline ocnfigurations ich haben und laden sie – Saravanan

+0

Ich habe kein funktionierendes Snippet, aber ich würde etwas wie versuchen: var mieter = new Liste () {new Tenant() {Subdomain = neue Subdomain ("organisation2")}}; var mieterFromContextParser = neu TenantFromContextParser(); foreach (var Mieter in Mieter) { portalApp.MapWhen (ctx => == tenant.Subdomain tenantFromContextParser.ParseFromHost (CTX) .OrganisationPart, perTenantApp => { perTenantApp.configurePerClient (.....); }); } –