2017-12-27 12 views
0

Für meine Website mache ich eine Integration mit einem Drittanbieter-Authentifizierungsanbieter, der OWIN OpenId verwendet, damit Besucher sich anmelden/an-/abmelden können. "Second"Doppelte OWIN-Authentifizierung funktioniert nicht

Ich habe auch eine Testumgebung für meine Anwendung, wo alle Codeänderungen getestet werden, bevor diese Änderungen in die Produktion übertragen werden. Ich schirmte die Testumgebung vor öffentlichem Zugriff mit einem anderen Drittanbieter-Authentifizierungsanbieter ab, wobei ich auch OWIN OpenId "First" verwendete. Nur authentifizierte Besucher können die Website der Testumgebung besuchen.

Jetzt ist das Problem, dass diese beide eigenständig arbeiten, aber ich kann nicht scheinen, sie zu kombinieren. Was ich versuche zu erreichen ist, dass ich auf die Testumgebung zugreifen kann, indem ich mich mit First authentifiziere und mich dann als regelmäßiger Besucher mit Second authentifiziere, um Inhalte zu sehen, die für registrierte Besucher gedacht sind.

Hier ist, was ich tue:

Beide authnetication Anbieter arbeiten mit Cookie-Authentifizierung, aber ich gab ihnen einen anderen AuthenticationType sie auseinander zu halten.

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

Wenn Zuerst aktiviert ist, dies ermöglicht es mir

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

auf nachfolgende Anfragen zu tun und eine ClaimsIdentity hat. Aber wenn First aktiviert ist, ist das obige Ergebnis aus irgendeinem Grund null.

Ich habe festgestellt, dass, wenn ich sowohl First und Second aktivieren, und setzen Sie die DefaultSignInAsAuthenticationType auf "Second", ist es zuerst, dass nicht mehr funktioniert. Wenn ich sowohl First als auch Second aktiviere und die Site mit einem früheren Authentifizierungscookie von First durchsuche, funktioniert alles einwandfrei.

Ich vermute, dass die Rückgabemethode, die irgendwo ein Authentifizierungs-Cookie setzt, eine Referenz von AuthenticationType benötigt, aber ich weiß nicht, wo ich das machen soll.

Was fehlt mir?

Antwort

1

Der Trick ist, die AuthenticationType zu TokenValidationParameters hinzuzufügen, wenn der zweiten Konfiguration, etwa so:

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 
     } 
}); 
Verwandte Themen