2016-03-02 15 views
7

I Identity Server 3 für einen zentralen Authentifizierungs-Server auf eine .NET MVC Web-Anwendung verwende ich baue.Azure AD föderierten Abmelde Umleitung nicht auf Client-Anwendung

Ich habe den Authentifizierungsserver so konfiguriert, dass der Identitätsanbieter Open ID Connect verwendet wird, damit sich Benutzer mithilfe des Hybrid-Datenflusses bei einem mandantenfähigen Azure Active Directory-Konto authentifizieren können.

Derzeit funktioniert die Anmeldung wie erwartet, wobei meine Clientanwendung zum Authentifizierungsserver umleitet, der wiederum zur Anmeldung an Microsoft umleitet, bevor er mit einem korrekt befüllten Zugriffstoken zu meiner Clientanwendung zurückkehrt.

Allerdings, wenn ich versuche, um die Abmeldung ich zu Microsoft richtig umgeleitet werde, aber die Seite stoppt, wenn es an dem Authentifizierungsserver kommt zurück, anstatt zurück zu meiner Client-Anwendung fort.

Ich glaube, ich habe die Post-Logout-Umleitung korrekt eingerichtet, wie beschrieben here und ich denke alle meine Einstellungen sind in Ordnung.

Wenn ich ziehen Sie den Identity Server 3 Code und debuggen, ist es richtig, die signOutMessageId auf die Query-String-Einstellung, aber trifft den folgenden Fehler in der UseAutofacMiddleware Methode, wenn es versucht, meine abgebildet signoutcallback Speicherort zu umleiten:

Ausnahme geworfen: 'System.InvalidOperationException' in mscorlib.dll

Zusätzliche Informationen: Header gesendet bereits

My Authentication Server-Setup:

app.Map("identity", idsrvApp => { 
    var idSvrFactory = new IdentityServerServiceFactory(); 

    var options = new IdentityServerOptions 
    {     
     SiteName = "Site Name", 
     SigningCertificate = <Certificate>, 
     Factory = idSvrFactory, 
     AuthenticationOptions = new AuthenticationOptions 
     { 
      IdentityProviders = ConfigureIdentityProviders, 
      EnablePostSignOutAutoRedirect = true, 
      PostSignOutAutoRedirectDelay = 3 
     } 
    }; 
    idsrvApp.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); 
    idsrvApp.UseIdentityServer(options); 

    idsrvApp.Map("/signoutcallback", cb => { 
        cb.Run(async ctx => { 
           var state = ctx.Request.Cookies["state"]; 
           ctx.Response.Cookies.Append("state", ".", new Microsoft.Owin.CookieOptions { Expires = DateTime.UtcNow.AddYears(-1) }); 
           await ctx.Environment.RenderLoggedOutViewAsync(state); 
        }); 
       }); 
}); 

Mein OpenID Connect Setup Azure AD verbinden:

app.UseOpenIdConnectAuthentication(
    new OpenIdConnectAuthenticationOptions 
    { 
     AuthenticationType = "aad", 
     SignInAsAuthenticationType = signInAsType, 

     Authority = "https://login.microsoftonline.com/common/", 
     ClientId = <Client ID>, 
     AuthenticationMode = AuthenticationMode.Active, 
     TokenValidationParameters = new TokenValidationParameters 
     { 
      AuthenticationType = Constants.ExternalAuthenticationType, 
      ValidateIssuer = false, 
     }, 
     Notifications = new OpenIdConnectAuthenticationNotifications() 
     { 
      AuthorizationCodeReceived = (context) => 
      { 
       var code = context.Code; 
       ClientCredential credential = new ClientCredential(<Client ID>, <Client Secret>); 
       string tenantId = context.AuthenticationTicket.Identity.FindFirst("tid").Value; 
       AuthenticationContext authContext = new AuthenticationContext($"https://login.microsoftonline.com/{tenantId}"); 
       AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
          code, new Uri(<Identity Server URI>/aad/"), credential, "https://graph.windows.net"); 

       return Task.FromResult(0); 
      }, 
      RedirectToIdentityProvider = (context) => 
      { 
       string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase; 
       context.ProtocolMessage.RedirectUri = appBaseUrl + "/aad/"; 
       context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl + "/signoutcallback"; 

       if (context.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.LogoutRequest) 
       { 
        var signOutMessageId = context.OwinContext.Environment.GetSignOutMessageId(); 
        if (signOutMessageId != null) 
        { 
         context.OwinContext.Response.Cookies.Append("state", signOutMessageId); 
        } 
       } 
       return Task.FromResult(0); 
      } 
    }); 

Ich kann keine Informationen über die Ursache oder Lösung für dieses Problem finden. Wie konfiguriere ich dies, um korrekt zurück zu meiner Client-Anwendung umzuleiten?

Edit:

Verwandte Diskussion auf GitHub: https://github.com/IdentityServer/IdentityServer3/issues/2657

Ich habe auch versucht, dies mit der neuesten Version von Identity Server auf MyGet (v2.4.1-build00452) mit dem gleichen Problem.

ich habe auch eine Repository, das hier für mich das Problem reproduziert: https://github.com/Steve887/IdentityServer-Azure/

Mein Azure AD Setup:

enter image description here

+0

Es gab eine Diskussion unter - https://github.com/IdentityServer/IdentityServer3/issues/1000 bezüglich dieser Funktion. Ich bin mir nicht sicher, ob dir das hilft. Hast du etwas in den IdServ3 Logs? – Karthik

+0

@Karthik Ich glaube, dass die Diskussion dazu geführt hat, dass die Methode "GetSignOutMessage" überhaupt erst eingeführt wurde. Und nein, nichts in den Protokollen, die ich sehen kann. – Steve

Antwort

0

Ich glaube, Sie einen Fehler wurden auftreten, das in 2.5 festgelegt ist (noch nicht von heute veröffentlicht): https://github.com/IdentityServer/IdentityServer3/issues/2678

+0

Wie ich bereits in der [GitHub-Ausgabe] (https://github.com/IdentityServer/IdentityServer3/issues/2657#issuecomment-196572981) erwähnt habe, habe ich den letzten Build von MyGet gezogen und es hat nicht funktioniert. – Steve

+0

Ok, dann müssen wir mehr Steve debuggen. –

0

Mit Stromquelle von Git, ich sehe immer noch dieses Problem. Es scheint mir, dass AuthenticationController.Logout während des Abmelde zweimal getroffen wird. Einmal vor der Abmelde-Seite des externen Anbieters wird angezeigt, und einmal danach.Der erste Aufruf Queues und löscht das Abmelde-Cookie, so dass es beim zweiten Rendern der Abmeldeseite nicht mehr verfügbar ist.

+0

Ich postete dies auf dem GitHub-Problem, aber ich werde es hier für die Nachwelt setzen, meine 'AuthenticationController.Logout' Methode wird nur einmal vor der Weiterleitung an den Upstream-Provider, so dass dies nicht der Grund ist. – Steve