Identityserver4: /connect/endsession from SPA client - missing logoutId

Created on 10 Oct 2016  路  11Comments  路  Source: IdentityServer/IdentityServer4

I've been following
https://damienbod.com/2016/03/02/angular2-openid-connect-implicit-flow-with-identityserver4/

to implement IdentityServer4 for a SPA application. We also have several resource backends, but those are not relevant here, I believe.

Everything seems to work fine, except for one thing - I cannot for the life of me get logout to work.

Here's the code that's run from securityService.ts as per the blog post above:

(never mind the additional TS services and variables - the url is correctly formed)

public logoff() {
        // /connect/endsession?id_token_hint=...&post_logout_redirect_uri=https://myapp.com
        console.log("BEGIN Logoff, no auth data");

        const idTokenHint = this._storageService.retrieve("authorizationDataIdToken");

        this._resourceService.getService(ResourceService.authorizationUrl)
            .subscribe((authorizationUrl: string) => {
                this._resourceService.getService(ResourceService.fagsystem)
                    .subscribe((fagsystem: string) => {
                        const url = authorizationUrl + "/connect/endsession" + "?" +
                            "id_token_hint=" + encodeURI(idTokenHint) + "&" +
                            "post_logout_redirect_uri=" + encodeURI(fagsystem + "/");

                        this.resetAuthorizationData();
                        window.location.href = url;
                    });
            });
    }

The /connect/endsession call redirects (302) to /account/logout - a GET method in the AccountController. I've implemented this from the sample repos. The Get method should call the POST method, which it doesn't - it redirects to the Logout.cshtml view because no logonId is set.

/// <summary>
        /// Show logout page
        /// </summary>
        [HttpGet]
        public async Task<IActionResult> Logout(string logoutId)
        {
            var context = await _interaction.GetLogoutContextAsync(logoutId);
            if (context?.ClientId != null)
            {
                // if the logout request is authenticated, it's safe to automatically sign-out
                return await Logout(new LogoutViewModel { LogoutId = logoutId });
            }

            var vm = new LogoutViewModel
            {
                LogoutId = logoutId
            };

            return View(vm);
        }

        /// <summary>
        /// Handle logout page postback
        /// </summary>
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Logout(LogoutViewModel model)
        {
            // delete authentication cookies
            await _signInManager.SignOutAsync();

            // set this so UI rendering sees an anonymous user
            HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity());

            // get context information (client name, post logout redirect URI and iframe for federated signout)
            var logout = await _interaction.GetLogoutContextAsync(model.LogoutId);

            var vm = new LoggedOutViewModel
            {
                PostLogoutRedirectUri = logout?.PostLogoutRedirectUri,
                ClientName = logout?.ClientId,
                SignOutIframeUrl = logout?.SignOutIFrameUrl
            };

            return Redirect(vm.PostLogoutRedirectUri);
            //return View("LoggedOut", vm);
        }

Question - why isn't the logout ID passed along to the Logout method from /connect/endsession?

Am I missing something on the /connect/endsession call?

question

Most helpful comment

I just tried to repro on the quickstart as you suggested, and it's working for me. Did you remember to update the PostLogoutRedirectUris to now have /signout-callback-oidc as the suffix? That's a change from 1.0 to 1.1 from Microsoft:

PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" }

All 11 comments

check the logs

Sorry. I'll go hide now. I'd overlooked the blatant error of forgetting to add a "/" to the post_logout_redirect_urls.

I upgrade my client from 1.0.0 to 1.1.0 and now logoutId is null in the server

That's happened to me also, after an upgrade logoutId is null.

It's easy to reproduce... Upgrade the Quickstart6_AspNetIdentity MvcClient to 1.1.0:

"Microsoft.NETCore.App": {
"version": "1.1.0",
"type": "platform"
},

Now use NuGet to update packages ...

I just tried to repro on the quickstart as you suggested, and it's working for me. Did you remember to update the PostLogoutRedirectUris to now have /signout-callback-oidc as the suffix? That's a change from 1.0 to 1.1 from Microsoft:

PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" }

Thank you Brock Allen!!!

You are right.

hi can any one let me know what is the fix for the mentioned issue -- logoutid not available for implicit flow?? I am also facing the same issue ? how is the logoff happening even though there is no logoutid?
I am still working with 1.0.0 version

PostLogoutRedirectUri is set for you automatically in the MW, so no need to set it explicitly.

@brockallen what does this mean?:

PostLogoutRedirectUri is set for you automatically in the MW, so no need to set it explicitly.

If you look at the configurations in the docs here, and here
They show the js client redirect as index.html:
PostLogoutRedirectUris = { "http://localhost:5003/index.html" },

I was referring to the ASP.NET OIDC security handler -- IOW, the client side component config, not IdentityServer's config.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings