{"action":"created","issue":{"url":"https://api.github.com/repos/IdentityServer/IdentityServer3/issues/2657","repository_url":"https://api.github.com/repos/IdentityServer/IdentityServer3","labels_url":"https://api.github.com/repos/IdentityServer/IdentityServer3/issues/2657/labels{/name}","comments_url":"https://api.github.com/repos/IdentityServer/IdentityServer3/issues/2657/comments","events_url":"https://api.github.com/repos/IdentityServer/IdentityServer3/issues/2657/events","html_url":"https://github.com/IdentityServer/IdentityServer3/issues/2657","id":137749708,"number":2657,"title":"Azure AD federated logout not redirecting to client application","user":{"login":"Steve887","id":129719,"avatar_url":"https://avatars2.githubusercontent.com/u/129719?v=4","gravatar_id":"","url":"https://api.github.com/users/Steve887","html_url":"https://github.com/Steve887","followers_url":"https://api.github.com/users/Steve887/followers","following_url":"https://api.github.com/users/Steve887/following{/other_user}","gists_url":"https://api.github.com/users/Steve887/gists{/gist_id}","starred_url":"https://api.github.com/users/Steve887/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Steve887/subscriptions","organizations_url":"https://api.github.com/users/Steve887/orgs","repos_url":"https://api.github.com/users/Steve887/repos","events_url":"https://api.github.com/users/Steve887/events{/privacy}","received_events_url":"https://api.github.com/users/Steve887/received_events","type":"User","site_admin":false},"labels":[{"id":73807330,"url":"https://api.github.com/repos/IdentityServer/IdentityServer3/labels/bug%20report","name":"bug report","color":"fc2929","default":false}],"state":"closed","locked":false,"assignee":{"login":"brockallen","id":649492,"avatar_url":"https://avatars0.githubusercontent.com/u/649492?v=4","gravatar_id":"","url":"https://api.github.com/users/brockallen","html_url":"https://github.com/brockallen","followers_url":"https://api.github.com/users/brockallen/followers","following_url":"https://api.github.com/users/brockallen/following{/other_user}","gists_url":"https://api.github.com/users/brockallen/gists{/gist_id}","starred_url":"https://api.github.com/users/brockallen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brockallen/subscriptions","organizations_url":"https://api.github.com/users/brockallen/orgs","repos_url":"https://api.github.com/users/brockallen/repos","events_url":"https://api.github.com/users/brockallen/events{/privacy}","received_events_url":"https://api.github.com/users/brockallen/received_events","type":"User","site_admin":false},"assignees":[{"login":"brockallen","id":649492,"avatar_url":"https://avatars0.githubusercontent.com/u/649492?v=4","gravatar_id":"","url":"https://api.github.com/users/brockallen","html_url":"https://github.com/brockallen","followers_url":"https://api.github.com/users/brockallen/followers","following_url":"https://api.github.com/users/brockallen/following{/other_user}","gists_url":"https://api.github.com/users/brockallen/gists{/gist_id}","starred_url":"https://api.github.com/users/brockallen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brockallen/subscriptions","organizations_url":"https://api.github.com/users/brockallen/orgs","repos_url":"https://api.github.com/users/brockallen/repos","events_url":"https://api.github.com/users/brockallen/events{/privacy}","received_events_url":"https://api.github.com/users/brockallen/received_events","type":"User","site_admin":false}],"milestone":null,"comments":33,"created_at":"2016-03-02T02:08:41Z","updated_at":"2017-08-18T16:41:03Z","closed_at":"2017-01-16T06:25:17Z","body":"- [x] I read and understood how to enable [logging](https://identityserver.github.io/Documentation/docsv2/configuration/logging.html)\n### Question / Issue\n\nI am using IdSvr for a central authentication server to a .Net MVC web application I am building.\n\nI have configured the authentication server to use the Open ID Connect identity provider in order to allow users to authenticate against a multi-tenant Azure Active Directory account, using the Hybrid flow.\n\nCurrently, sign in works as expected with my client application redirecting to the authentication server which in turn redirects to Microsoft for login before returning back to my client application with a correctly populated Access Token.\n\nHowever, when I try to logout I am redirected to Microsoft correctly, but the page stops when it arrives back at the authentication server, rather than continuing back to my client application.\n\nI believe I have setup the post logout redirect correctly as outlined [here](https://identityserver.github.io/Documentation/docsv2/advanced/federated-post-logout-redirect.html) and I _think_ all of my settings are ok.\n\nWhen I pull the Identity Server 3 code down and debug it, it is correctly setting the `signOutMessageId` onto the query string, but hits the following error inside the `UseAutofacMiddleware` method when it is trying to redirect to my mapped `signoutcallback` location:\n\n> Exception thrown: 'System.InvalidOperationException' in mscorlib.dll\n> \n> Additional information: Headers already sent\n\nMy Authentication Server setup:\n\n```\napp.Map(\"identity\", idsrvApp => {\n    var idSvrFactory = new IdentityServerServiceFactory();\n\n    var options = new IdentityServerOptions\n    {                \n        SiteName = \"Site Name\",\n        SigningCertificate = <Certificate>,\n        Factory = idSvrFactory,\n        AuthenticationOptions = new AuthenticationOptions\n        {\n            IdentityProviders = ConfigureIdentityProviders,\n            EnablePostSignOutAutoRedirect = true,\n            PostSignOutAutoRedirectDelay = 3\n        }\n    };\n    idsrvApp.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);\n    idsrvApp.UseIdentityServer(options);\n\n    idsrvApp.Map(\"/signoutcallback\", cb => {\n                    cb.Run(async ctx => {\n                               var state = ctx.Request.Cookies[\"state\"];\n                               await ctx.Environment.RenderLoggedOutViewAsync(state);\n                    });\n                });\n});\n```\n\nMy Open Id Connect setup to connect to Azure AD:\n\n```\napp.UseOpenIdConnectAuthentication(\n    new OpenIdConnectAuthenticationOptions\n    {\n        AuthenticationType = \"aad\",\n        SignInAsAuthenticationType = signInAsType,\n\n        Authority = \"https://login.microsoftonline.com/common/\",\n        ClientId = <Client ID>,\n        AuthenticationMode = AuthenticationMode.Active,\n        TokenValidationParameters = new TokenValidationParameters\n        {\n            AuthenticationType = Constants.ExternalAuthenticationType,\n            ValidateIssuer = false,\n        },\n        Notifications = new OpenIdConnectAuthenticationNotifications()\n        {\n            AuthorizationCodeReceived = (context) =>\n            {\n                var code = context.Code;\n                ClientCredential credential = new ClientCredential(<Client ID>, <Client Secret>);\n                string tenantId = context.AuthenticationTicket.Identity.FindFirst(\"tid\").Value;\n                AuthenticationContext authContext = new AuthenticationContext($\"https://login.microsoftonline.com/{tenantId}\");\n                AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(\n                            code, new Uri(<Identity Server URI\"), credential, \"https://graph.windows.net\");\n\n                return Task.FromResult(0);\n            },\n            RedirectToIdentityProvider = (context) =>\n            {\n                string appBaseUrl = context.Request.Scheme + \"://\" + context.Request.Host + context.Request.PathBase;\n                context.ProtocolMessage.RedirectUri = appBaseUrl + \"/\";\n                context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl + \"/signoutcallback\";\n\n                if (context.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.LogoutRequest)\n                {\n                    var signOutMessageId = context.OwinContext.Environment.GetSignOutMessageId();\n                    if (signOutMessageId != null)\n                    {\n                        context.OwinContext.Response.Cookies.Append(\"state\", signOutMessageId);\n                    }\n                }\n                return Task.FromResult(0);\n            }\n    });\n```\n\nI cannot find any information about the cause of or solution to this problem. How do I configure this to correctly redirect back to my client application?\n"},"comment":{"url":"https://api.github.com/repos/IdentityServer/IdentityServer3/issues/comments/323402666","html_url":"https://github.com/IdentityServer/IdentityServer3/issues/2657#issuecomment-323402666","issue_url":"https://api.github.com/repos/IdentityServer/IdentityServer3/issues/2657","id":323402666,"user":{"login":"iulypop2003","id":31131757,"avatar_url":"https://avatars0.githubusercontent.com/u/31131757?v=4","gravatar_id":"","url":"https://api.github.com/users/iulypop2003","html_url":"https://github.com/iulypop2003","followers_url":"https://api.github.com/users/iulypop2003/followers","following_url":"https://api.github.com/users/iulypop2003/following{/other_user}","gists_url":"https://api.github.com/users/iulypop2003/gists{/gist_id}","starred_url":"https://api.github.com/users/iulypop2003/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iulypop2003/subscriptions","organizations_url":"https://api.github.com/users/iulypop2003/orgs","repos_url":"https://api.github.com/users/iulypop2003/repos","events_url":"https://api.github.com/users/iulypop2003/events{/privacy}","received_events_url":"https://api.github.com/users/iulypop2003/received_events","type":"User","site_admin":false},"created_at":"2017-08-18T16:41:03Z","updated_at":"2017-08-18T16:41:03Z","body":"For idsrv3 it didn't work for me, but as workaround I made a redirect to the logout page.\r\nAnother thing, i passed the state to the external provider, instead of having in the cookie; this works for both OKTA and Azure AD.\r\n\r\ninstead of:\r\n```\r\nidsrvApp.Map(\"/signoutcallback\", cb => {\r\n                    cb.Run(async ctx => {\r\n                               var state = ctx.Request.Cookies[\"state\"];\r\n                               await ctx.Environment.RenderLoggedOutViewAsync(state);\r\n                    });\r\n                });\r\n```\r\nand\r\n\r\n```\r\nif (context.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.LogoutRequest)\r\n                {\r\n                    var signOutMessageId = context.OwinContext.Environment.GetSignOutMessageId();\r\n                    if (signOutMessageId != null)\r\n                    {\r\n                        context.OwinContext.Response.Cookies.Append(\"state\", signOutMessageId);\r\n                    }\r\n                }\r\n```\r\n\r\nhave this:\r\n```\r\nidsrvApp.Map(\"/signoutcallback\", cb => {\r\n                    cb.Run(async ctx => {\r\n                               cb.Run(async ctx =>\r\n                                {\r\n                                    //var state = ctx.Request.Cookies[\"state\"];\r\n                                    var state = ctx.Request.Query.Get(\"state\");\r\n                                    ctx.Response.Redirect(ctx.Request.Uri.AbsoluteUri.Replace(\"/signoutcallback?state=\",\"/logout?id=\"));\r\n                                    await Task.FromResult(true);\r\n                                });\r\n                    });\r\n                });\r\n```\r\nand\r\n\r\n```\r\nif (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)\r\n                        {                            \r\n                            var signOutMessageId = n.OwinContext.Request.Query.Get(\"id\");\r\n                            //var signOutMessageId = context.OwinContext.Environment.GetSignOutMessageId();\r\n                            //if (signOutMessageId != null)\r\n                            //{\r\n                            //    n.OwinContext.Response.Cookies.Append(\"state\", signOutMessageId);\r\n                            //}\r\n\r\n                            if (id_token != null)\r\n                            {\r\n                                n.ProtocolMessage.IdTokenHint = id_token; //this is mandatory for okta\r\n                                n.ProtocolMessage.State = signOutMessageId;\r\n                            }\r\n                        }\r\n```\r\n"}}
{"actor":{"display_login":"iulypop2003"}}