2017-12-27 570 views
0

對於我的網站,我正在使用OWIN OpenId與第三方身份驗證提供程序進行集成,以允許訪問者註冊/登錄/註銷。 「Second」雙OWIN身份驗證不能一起工作

對於我的應用程序,我還有一個測試環境,在將這些更改推送到生產之前,測試所有代碼更改。我將測試環境與另一個第三方身份驗證提供程序的公共訪問隔開,並使用OWIN OpenId以及「First」。只有經過驗證的訪問者才能訪問測試環境網站。

現在的問題是,這兩個工作是獨立的,但我似乎無法將它們結合起來。我試圖實現的是,我可以通過使用First進行身份驗證來訪問測試環境,然後作爲regluar訪問者使用Second進行身份驗證,以查看爲註冊訪問者設計的內容。

下面是我在做什麼:

兩個authnetication提供商與cookie認證工作,但我給了他們一個不同的AuthenticationType把它們分開。

if (IsEnabled("First")) 
    app.SetDefaultSignInAsAuthenticationType("First"); 
else 
    app.SetDefaultSignInAsAuthenticationType("Second"); 

// Configure First. 
if (IsEnabled("First")) { 
    app.UseCookieAuthentication(First.CookieAuthenticationOptions); // AuthenticationType is set to "First" in these options. 
    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
    { 
     ClientId = First.AADClientId, 
     Authority = First.Authority, 
     Notifications = new OpenIdConnectAuthenticationNotifications 
     { 
      AuthenticationFailed = context => { ... }, 
      RedirectToIdentityProvider = context => { ... } 
     }, 
     AuthenticationType = "First" 
    }); 
    app.Map($"{First.Path}/login", config => 
    { 
     config.Run(context => 
     { 
      context.Authentication.Challenge(new AuthenticationProperties 
       { RedirectUri = First.ReturnUrl, IsPersistent = true }, 
       "First" 
      ); 

      context.Response.StatusCode = 401; 
      return context.Response.WriteAsync(string.Empty); 
     }); 
    }); 
} 

// Configure Second. 
app.UseCookieAuthentication(Second.CookieAuthenticationOptions); // AuthenticationType is set to "Second" in these options. 
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
{ 
    UseTokenLifetime = false, 
    Notifications = new OpenIdConnectAuthenticationNotifications 
    { 
     AuthenticationFailed = x => ..., 
     RedirectToIdentityProvider = x => 
     { 
      var mgr = x.Options.ConfigurationManager as PolicyConfigurationManager; 
      if (x.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest) 
      { 
       var config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None, 
       x.OwinContext.Authentication.AuthenticationResponseRevoke.Properties.Dictionary["PolicyId"]); 
       x.ProtocolMessage.IssuerAddress = config.EndSessionEndpoint; 
      } 
      else 
      { 
       var config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None, 
       x.OwinContext.Authentication.AuthenticationResponseChallenge.Properties.Dictionary["PolicyId"]); 
       x.ProtocolMessage.IssuerAddress = config.AuthorizationEndpoint; 
      } 

      var redirectUri = Second.ReturnPath; 
      x.ProtocolMessage.RedirectUri = redirectUri; 
      x.ProtocolMessage.PostLogoutRedirectUri = redirectUri; 
     }, 
     SecurityTokenValidated = x => ... 
    }, 
    Scope = "openid", 
    ResponseType = "id_token", 
    ReturnUri = Second.ReturnUri, 
    ClientId = Second.ClientId, 
    ConfigurationManager = GetConfigurationManager() 
    AuthenticationType = configuration.AuthenticationType 
}); 
app.Map(Second.LoginPath, config => 
{ 
    // Trigger unauthorized so that active authentication will redirect to active directory. 
    config.Run(context => 
    { 
     // Set policy in context to mitigate null ref exception in Startup.Auth OnRedirectToIdentityProvider 
     context.Authentication.Challenge(
      new AuthenticationProperties(new Dictionary<string, string> 
      { 
       {"PolicyId", Second.LoginPolicyId} 
      }) 
      { 
       IsPersistent = true, 
       RedirectUri = returnUrl 
      }, "Second"); 

     context.Response.StatusCode = 401; 

     // Middleware will redirect us instead of using this output. 
     return context.Response.WriteAsync(string.Empty); 
    }); 
}); 
app.Map(Second.ReturnPath, config => 
{ 
    config.Use((context, next) => 
    { 
     // In case of login, we will never get here because we will get redirected by middleware. 
     context.Response.Redirect("/"); 

     return Task.FromResult(0); 
    }); 
}); 

當第一次啓用,這允許我做

var identity = HttpContext.Current.GetOwinContext.Authentication.AuthenticateAsync("Second").Result?.Identity; 

在後續請求中,有一個ClaimsIdentity。但是,當First啓用時,出於某種原因,上述結果爲空。

我注意到,當我啓用第一和第二,並將DefaultSignInAsAuthenticationType設置爲「第二」,它是第一個不再工作。如果我同時啓用First和Second,並使用First的先前身份驗證Cookie瀏覽網站,則一切正常。

我猜測返回方法,某處設置身份驗證cookie需要一些AuthenticationType的引用,但我不知道該在哪裏做。

我缺少什麼?

回答

1

訣竅是第二配置時AuthenticationType添加到TokenValidationParameters,像這樣:

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
{ 
    UseTokenLifetime = false, 
    Notifications = new OpenIdConnectAuthenticationNotifications 
    { 
     AuthenticationFailed = x => ..., 
     RedirectToIdentityProvider = x => 
     { 
      var mgr = x.Options.ConfigurationManager as PolicyConfigurationManager; 
      if (x.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest) 
      { 
       var config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None, 
       x.OwinContext.Authentication.AuthenticationResponseRevoke.Properties.Dictionary["PolicyId"]); 
       x.ProtocolMessage.IssuerAddress = config.EndSessionEndpoint; 
      } 
      else 
      { 
       var config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None, 
       x.OwinContext.Authentication.AuthenticationResponseChallenge.Properties.Dictionary["PolicyId"]); 
       x.ProtocolMessage.IssuerAddress = config.AuthorizationEndpoint; 
      } 

      var redirectUri = Second.ReturnPath; 
      x.ProtocolMessage.RedirectUri = redirectUri; 
      x.ProtocolMessage.PostLogoutRedirectUri = redirectUri; 
     }, 
     SecurityTokenValidated = x => ... 
    }, 
    Scope = "openid", 
    ResponseType = "id_token", 
    ReturnUri = Second.ReturnUri, 
    ClientId = Second.ClientId, 
    ConfigurationManager = GetConfigurationManager(), 
    AuthenticationType = configuration.AuthenticationType, 
    // ADD THIS TO MAKE IT WORK: 
    TokenValidationParameters = new TokenValidationParameters 
     { 
      AuthenticationType = configuration.AuthenticationType 
     } 
});