2016-03-02 16 views
7

Korzystam z Identity Server 3 dla centralnego serwera uwierzytelniania do aplikacji sieci web .Net MVC, którą buduję.Wylogowanie stowarzyszone Azure AD nie przekierowujące do aplikacji klienckiej

Skonfigurowałem serwer uwierzytelniania do korzystania z dostawcy tożsamości Open ID Connect, aby umożliwić użytkownikom uwierzytelnianie się na koncie Azure Active Directory z wieloma dzierżawcami, używając przepływu hybrydowego.

Obecnie logowanie działa zgodnie z oczekiwaniami, gdy moja aplikacja kliencka przekierowuje na serwer uwierzytelniania, który z kolei przekierowuje do firmy Microsoft w celu zalogowania się, a następnie wraca do mojej aplikacji klienckiej z poprawnie wypełnionym tokenem dostępu.

Jednak, gdy próbuję się wylogować, jestem przekierowywany do firmy Microsoft poprawnie, ale strona zatrzymuje się, gdy wraca na serwer uwierzytelniania, zamiast kontynuować z powrotem do aplikacji klienckiej.

Wydaje mi się, że poprawnie skonfigurowałem przekierowanie po wylogowaniu zgodnie z opisem here i I pomyśl wszystkie moje ustawienia są prawidłowe.

Kiedy wyciągnąć Identity Server 3 Kod dół i debugowania to, że jest prawidłowo zachodzące signOutMessageId na ciąg kwerendy, ale piłka uderza w następujący błąd wewnątrz metody UseAutofacMiddleware gdy próbuje przekierować do mojego odwzorowanym signoutcallback lokalizacji:

rzucony wyjątek: 'System.InvalidOperationException' w pliku mscorlib.dll

Dodatkowe informacje: nagłówki już wysłane

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

setup My Otwarte Id Połącz, aby połączyć się Azure AD:

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

nie mogę znaleźć żadnych informacji na temat przyczyny i rozwiązania tego problemu. Jak skonfigurować to, aby poprawnie przekierować z powrotem do mojej aplikacji klienckiej?

Edit:

Powiązane dyskusja na GitHub: https://github.com/IdentityServer/IdentityServer3/issues/2657

Próbowałem to także z najnowszą wersją Identity Server na MyGet (v2.4.1-build00452) z tym samym problemem.

Mam również utworzone repozytorium, które reprodukuje problem dla mnie tutaj: https://github.com/Steve887/IdentityServer-Azure/

Moja Azure konfiguracja AD:

enter image description here

+0

Przeprowadzono dyskusję na stronie - https://github.com/IdentityServer/IdentityServer3/issues/1000 dotyczącej tej funkcji. Nie jestem pewien, czy to ci pomoże. Czy masz coś w dziennikach IdServ3? – Karthik

+0

@Karthik Wierzę, że dyskusja doprowadziła w pierwszej kolejności do wdrożenia metody "GetSignOutMessage". I nie, nic w dziennikach, które widzę. – Steve

Odpowiedz

0

Wierzę, że doświadczali błąd, który został rozwiązany w 2,5 (jeszcze nie opublikowany od dzisiaj): https://github.com/IdentityServer/IdentityServer3/issues/2678

+0

Jak wspomniałem w wydaniu [GitHub] (https://github.com/IdentityServer/IdentityServer3/issues/2657#issuecomment-196572981) Wyciągnąłem najnowszą kompilację z MyGet i nie zadziałało. – Steve

+0

Ok, musimy zdebugować więcej Steve'a. –

0

Używając obecnego źródła z Git, nadal widzę ten problem. Wydaje mi się, że AuthenticationController.Logout jest dwukrotnie trafiony podczas wylogowania. Raz przed wyświetleniem strony wylogowania zewnętrznego dostawcy i raz po.Początkowe połączenie Kolejki i czyści plik cookie wylogowania, aby po raz drugi nie był dostępny podczas renderowania strony wylogowania.

+0

Opublikowalem to w wydaniu GitHub, ale umieścimy je tutaj dla potomności, moja metoda 'AuthenticationController.Logout' pobiera go tylko raz przed przekierowaniem do dostawcy zewnętrznego, więc to nie jest przyczyną. – Steve

Powiązane problemy