2

I am currently working with Identity server 4, where i am trying to enable BackChannelLogoutUri.

Each client has been given a BackChannelLogoutUri in the config of the client

BackChannelLogoutUri = "http://localhost:44322/home/LogoutBackChannel",

Each client application has registered the cookieEventHandler and LogoutSessionManager.

services.AddTransient<CookieEventHandler>();
        services.AddSingleton<LogoutSessionManager>();

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = "oidc";
        })
            .AddCookie(options =>
            {
                options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
                options.Cookie.Name = "mvchybridbc";

                options.EventsType = typeof(CookieEventHandler);
            })

My logout view on the identity server contains the Iframe

@if (Model.PostLogoutRedirectUri != null)
{
    <div>
        Click <a class="PostLogoutRedirectUri" href="@Model.PostLogoutRedirectUri">here</a> to return to the
        <span>@Model.ClientName</span> application.
    </div>
}
@if (Model.SignOutIframeUrl != null)
{
    <iframe width="0" height="0" class="signout" src="@Model.SignOutIframeUrl"></iframe>
}

This is all well and good. But my problem is that the BackChannelLogoutUri is a single url. When hosted it will need to be passed some how from each tennent

We cant really have a client for each tenant and app. That would be a lot of clients. That and clients that are only users of tenant one would not need to be logged out of tenant two.

I am not sure how to address this issue.

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449

1 Answers1

4

I've implemented the backchannel logout without having to rely on iframes. What it basically does is, collect the necessary urls and then send the notifications.

I don't have tenants, so this will work for me. But you can adapt the code and add the logic for tenants, as commented in the code:

// Injected services:

//private readonly IUserSession _userSession;
//private readonly IClientStore _clientStore;
//private readonly IBackChannelLogoutService _backChannelClient;

private async Task LogoutUserAsync(string logoutId)
{
    if (User?.Identity.IsAuthenticated == true)
    {
        // delete local authentication cookie
        await HttpContext.SignOutAsync();

        // Get all clients from the user's session
        var clientIds = await _userSession.GetClientListAsync();
        if (clientIds.Any())
        {
            var backChannelClients = new List<BackChannelLogoutModel>();
            var sessionId = await _userSession.GetSessionIdAsync();
            var sub = User.Identity.GetSubjectId();

            foreach (var clientId in clientIds)
            {
                var client = await _clientStore.FindEnabledClientByIdAsync(clientId);
                // This should be valid in any case:
                if (client == null && !string.IsNullOrEmpty(client.BackChannelLogoutUri))
                    continue;

                // Insert here the logic to retrieve the tenant url for this client
                // and replace the uri:
                var tenantLogoutUri = client.BackChannelLogoutUri;

                backChannelClients.Add(new BackChannelLogoutModel
                {
                    ClientId = client.ClientId,
                    LogoutUri = tenantLogoutUri,
                    SubjectId = sub,
                    SessionId = sessionId,
                    SessionIdRequired = true
                });
            }

            try
            {
                await _backChannelClient.SendLogoutNotificationsAsync(backChannelClients);
            }
            catch (Exception ex)
            {
                // Log message
            }
        }

        // raise the logout event
        await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName()));
    }
}
  • Now i just need to figure out where IBackChannelLogoutService comes from – Linda Lawton - DaImTo Sep 04 '19 at 09:57
  • Be sure to get the latest version of IdentityServer. This is a new feature. –  Sep 04 '19 at 09:58
  • Ack not sure i can get permission to update this server I will have to check – Linda Lawton - DaImTo Sep 04 '19 at 09:58
  • Being open source you can also implement this yourself. At first I created and injected my own code. Later removed it because it is part of the new version. –  Sep 04 '19 at 10:00
  • 2
    Take a look at [the code](https://github.com/IdentityServer/IdentityServer4/blob/53d3b7f5c4415a733d8392b3c3a85c3adf17646b/src/IdentityServer4/src/Services/Default/DefaultBackChannelLogoutService.cs). –  Sep 04 '19 at 10:01