safinilnur
safinilnur

Reputation: 317

IdentityServer - pass extra params from endsession endpoint to Logout

How we can pass extra params (which we send as query params to endsession endpoint) to Logout when user is not authenticated in IDP SSO

I'm using latest Identity Server 4.

In the standard case, when client initiates a logout (by accessing endsession endpoint), everything works fine when we have information about the user (which is stored in a cookie and endsession endpoint can successfully read that). EndSession redirects to https://myidp/Account/Logout?logoutId=someId and we can get any parameter which was passed in query string to endsession endpoint

But when we try to do second logout from the client (and there is no authenticated user in cookie), logoutId parameter is not passed to Logout endpoint and there is no chance to get params which we sent in query string to endsession endpoint

The reason why we need this is simple:

  1. suppose client clicked logout twice on 2 different pages (client's pages)
  2. when user was logged out, we want to redirect it back to client URL OR to add some extra logic depending on params which we send to endsession endpoint. But as we don't get any params in Logout method - we don't know anything about the client and what to do with this logout request

Upvotes: 2

Views: 1068

Answers (1)

safinilnur
safinilnur

Reputation: 317

For now as workaround of this problem I added middleware in .Net Core app, which validates LogoutId parameter. If it doesn't exist (the case when we will not be able to get initial parameters, as no logoutId was passed in the query string to logout method), I add manually query string parameters from my middleware to the redirected URL

using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;

namespace IdentityProviderWebApp.Core
{
    public class EndRequestMiddleware
    {
        private readonly RequestDelegate _next;

        public EndRequestMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            await _next(context);

            if (context.Request.Path.Value == "/connect/endsession")
            {
                var logoutUrl = context.Response.Headers["location"].ToString();

                if (!logoutUrl.Contains("?"))
                {
                    var fixedLocation = context.Response.Headers["location"] + context.Request.QueryString;

                    context.Response.Headers.Remove("location");
                    context.Response.Headers.Add("location", new StringValues(fixedLocation));
                }
            }
        }
    }
}

Register middleware code

app.UseMiddleware<EndRequestMiddleware>();

In AccountController Logout method get your expected variables as parameters of logout method

public async Task<IActionResult> Logout(string logoutId, string client_id, string redirect_uri)

In the Logout method get actual variable either from a valid context (if LogoutId exists) or use value which you receive in your Logout method

var logout = await _interaction.GetLogoutContextAsync(logoutId);

clientId = logout.Parameters.Get("client_id") ?? clientId;
redirectUri = logout.Parameters.Get("redirect_uri") ?? redirectUri;

Hope someone will find better approach

Upvotes: 3

Related Questions