using System; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.Owin; using Owin; using Sitecore.Abstractions; using Sitecore.Diagnostics; using Custom.Owin.Authentication.Extensions; using Sitecore.Owin.Pipelines.Initialize; namespace Custom.Owin.Authentication.IdentityServer.Pipelines.Initialize { [Sitecore.Annotations.UsedImplicitly] public class LogoutEndpoint : InitializeProcessor { [Sitecore.Annotations.NotNull] private readonly BaseSiteContextFactory _siteContextFactory; [Sitecore.Annotations.NotNull] private readonly BaseAuthenticationManager _baseAuthenticationManager; public LogoutEndpoint([Sitecore.Annotations.NotNull] BaseSiteContextFactory siteContextFactory, [Sitecore.Annotations.NotNull] BaseAuthenticationManager baseAuthenticationManager) { Assert.ArgumentNotNull(siteContextFactory, nameof(siteContextFactory)); Assert.ArgumentNotNull(baseAuthenticationManager, nameof(baseAuthenticationManager)); _siteContextFactory = siteContextFactory; _baseAuthenticationManager = baseAuthenticationManager; } public override void Process([Sitecore.Annotations.NotNull] InitializeArgs args) { Assert.ArgumentNotNull(args, nameof(args)); foreach (var virtualFolder in _siteContextFactory.GetSites().Select(site => site.VirtualFolder).Distinct()) { if (string.IsNullOrEmpty(virtualFolder)) { continue; } args.App.MapEx(virtualFolder + "FrontChannelLogout", builder => { builder.Run(Handler); }); } } private async Task Handler(IOwinContext context) { context.Response.ContentType = "text/html"; context.Response.StatusCode = 400; if (!(context.Request.User?.Identity is ClaimsIdentity claimsIdentity)) { await context.Response.WriteAsync("ClaimsIdentity was not found.").ConfigureAwait(false); return; } bool isAuthenticated = claimsIdentity.IsAuthenticated; if (!isAuthenticated) { await context.Response.WriteAsync("User is not authenticated.").ConfigureAwait(false); return; } string requestSid = context.Request.Query.Get("sid"); if (string.IsNullOrEmpty(requestSid)) { await context.Response.WriteAsync("Requested sid was not found.").ConfigureAwait(false); return; } string currentSid = claimsIdentity.FindFirst("sid")?.Value ?? ""; if (string.Equals(currentSid, requestSid, StringComparison.Ordinal)) { _baseAuthenticationManager.Logout(); context.Response.StatusCode = 200; await context.Response.WriteAsync("User was logged out.").ConfigureAwait(false); } else { await context.Response.WriteAsync("A sid of authenticated user is not equal a requested sid.").ConfigureAwait(false); } } } }