2016-06-20 7 views
3

私は、各テナントがWsFedまたはOpenIdConnect(Azure)またはShibboleth(Kentor)に対して独自のMetaData URl、ClientId、Authorityなどを定義できるマルチテナントアプリケーションを用意しています。すべてのテナントは、DBテーブルに格納され、以下のようにOwinStartupに登録されている:同じプロバイダ(ADFS、アズールまたはShibbolethの)複数のorgnaizationsをdBで有効になっている場合OWINパイプラインを使用したマルチテナント認証

 // 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; 
     } 
    } 

、私はエラーを取得します。私はそれを拡張するために "app.Map"を試しました。しかし、失敗しました。また、以下のコードを使用してすべてのプロバイダ(ADFSとAzure)をログアウトしますが、ログアウトも失敗します。

プロバイダは一意です認証タイプ私は組織全体で使用しています。

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

ヘルプ/ガイダンスをお探しですか? 注:新しいテナントが追加されるたびに、appdomainをリサイクルするようにして、パイプラインを動的に再構築して複雑なものにする必要はありません。

答えて

0

Kentor.AuthServicesミドルウェアは複数のインスタンスをサポートしますが、それぞれにModulePathという特定のものを割り当てる必要があります。それがなければ、最初のKentor.AuthServicesミドルウェアはすべての着信要求を処理し、他のインスタンスで設定されたIdentityProviderからのメッセージにエラーを投げます。

他のKatanaプロバイダの中には、コールバック時に使用される同様の「隠れた」エンドポイントがあることは知っていますが、複数のミドルウェアインスタンスがロードされた場合の動作はわかりません。

また、Kentor.AuthServicesミドルウェアは、複数のアイデンティティプロバイダを1つのインスタンスに登録することもサポートしています。次に、実行時にIdentityProviderインスタンスをKentorAuthServicesAuthenticationOptionsに追加してrmoveし、すぐに有効にします。ただし、他のプロトコルにテナントごとに1つのミドルウェアを使用している場合は、理想的なソリューションではない可能性があります。

+0

モジュールパスを追加する方法についてのスニペットを表示できます – Saravanan

+0

それは 'SPOptions'のプロパティです –

+0

プロバイダごとに、IDPからそれぞれのauthserviesを提供する必要がありますか? – Saravanan

0

MapWhenも機能を受け入れるので、あなたはできる(CTX => ctx.configureSpecificTenantは、「tenant1」)app.MapWhenで条件に基づいてテナントごとに異なるowinパイプラインを作成することはできませんリストのforeach反復を伴うサブドメインのようないくつかの他の条件に基づいています。

+0

あなたは働くスニペットを共有できますか?テナント1はURLパスのみで識別できます。つまり、http://www.tenant1。それで、それに基づいて、私が持っているパイプラインの設定と一致させる必要があると – Saravanan

+0

私は動作しているスニペットを持っていないが、私は何かのようにしようとします: varテナント=新しいリスト(){新しいテナント(){サブドメイン=新しいサブドメイン( "organisation2")}}; var tenantFromContextParser = new TenantFromContextParser(); foreachの(テナントでVARテナント) {portalApp.MapWhen(CTX => tenant.Subdomain == tenantFromContextParser.ParseFromHost(CTX).OrganisationPart、 perTenantApp => { perTenantApp.configurePerClient(.....); }); } –

関連する問題