Create a new processor to validate a single session on <owin.cookieAuthentication.signedIn>
pipeline, if the same username is already logged in on other devices, we kick out the session and then remove the user's ticket from Sitecore TicketManager.
App_Config\Sitecore\Owin.Authentication\Sitecore.Owin.Authentication.config
<configuration>
<sitecore>
<pipelines>
<owin.cookieAuthentication.signIn>
<processor resolve="true" type="your.SIGN-IN.pipeline, YourDLL" patch:after="processor[@type='Sitecore.Owin.Authentication.Pipelines.CookieAuthentication.SignIn.RemoveTicket, Sitecore.Owin.Authentication']" />
</owin.cookieAuthentication.signIn>
</pipelines>
</sitecore>
</configuration>
Create ValidateSingleSession
class inherit from SignedInProcessor
using System;
using Sitecore.Abstractions;
using Sitecore.Owin.Authentication.Pipelines.CookieAuthentication.SignedIn;
using Sitecore.Web.Authentication;
using System.Collections.Generic;
namespace Sitecore.SitecoreExtensions.Owin.Authentication.Pipelines
{
public class ValidateSingleSession : SignedInProcessor
{
protected BaseTicketManager TicketManager { get; }
public ValidateSingleSession(BaseTicketManager ticketManager)
{
this.TicketManager = ticketManager;
}
public override void Process(SignedInArgs args)
{
if (!string.Equals(args.Site.Name, "shell", StringComparison.Ordinal))
return;
var validateSingleSession = Sitecore.Configuration.Settings.GetSetting("Security.ValidateSingleSession");
if (!bool.Parse(validateSingleSession))
return;
List<DomainAccessGuard.Session> userSessionList = DomainAccessGuard.Sessions;
if (userSessionList != null && userSessionList.Count > 0)
{
foreach (DomainAccessGuard.Session userSession in userSessionList.ToArray())
{
if (args.User.UserName == userSession.UserName)
{
DomainAccessGuard.Kick(userSession.SessionID);
Sitecore.Diagnostics.Log.Audit($"Concurrent sessions detected: User {userSession.UserName} is kicked out ", this);
}
}
}
//remove ticket
var ticketIds = this.TicketManager.GetTicketIDs();
if (ticketIds != null && ticketIds.Count > 0)
{
foreach (var ticketID in ticketIds)
{
var ticket = this.TicketManager.GetTicket(ticketID);
if (args.User.UserName == ticket.UserName)
{
this.TicketManager.RemoveTicket(ticketID);
}
}
}
}
}
}
Also created a field to allow the development team to disable single-session validation by introducing Security.ValidateSingleSession
setting in config.
For more detailes visit the link - https://edwenkerk.hashnode.dev/sitecore-10-single-login-session-and-kick-idle-user