using e_suite.API.Common.exceptions; using e_suite.API.Common.models; using e_suite.Database.Audit; using eSuite.API.Extensions; using eSuite.API.Middleware; using eSuite.Core.Miscellaneous; using IUserManager = e_suite.API.Common.IUserManager; // ReSharper disable All namespace eSuite.API.SingleSignOn; /// /// Internal class used to manage cookies /// public class CookieManager : ICookieManager { private readonly IUserManager _userManager; /// /// Default constructor /// /// public CookieManager(IUserManager userManager) { _userManager = userManager; } private const string ssoNewUserLinkCookieName = "eSuiteNewUserLinkCookie"; private const string ssoProfileLinkCookieName = "eSuiteProfileLinkCookie"; private const string ssoIdCookieName = "eSuiteSsoProvider"; /// /// Creates the session cookie with appropriate settings /// /// /// /// public Task CreateSessionCookie(HttpResponse response, LoginResponse loginResponse) { response.Cookies.Append(AuthenticationExtension.SessionCookieName, loginResponse.Token, new CookieOptions { HttpOnly = false, //Set False as Javascript (React) needs to read the cookie. SameSite = SameSiteMode.Strict, Secure = true, IsEssential = true, Expires = null, //Session Cookie Path = "/" }); return Task.CompletedTask; } /// /// Deletes any existing session cookie /// /// /// public Task DeleteSessionCookie(HttpResponse response) { response.Cookies.Delete(AuthenticationExtension.SessionCookieName); return Task.CompletedTask; } /// /// Creates cookie used with an Sso Identity to a user account /// /// /// /// /// /// public async Task CreateProfileLinkCookie(HttpResponse response, AuditUserDetails auditUserDetails, GeneralIdRef generalIdRef, CancellationToken cancellationToken) { var guid = await _userManager.CreateSingleUseGuid(auditUserDetails, generalIdRef, cancellationToken); response.Cookies.Append(ssoProfileLinkCookieName, guid.ToString(), new CookieOptions { HttpOnly = true, //Set True only the server side app needs to know about this SameSite = SameSiteMode.Lax, //Used when returning from an sso authorisation Secure = true, IsEssential = true, Expires = null, //Session Cookie Path = "/" }); } /// /// Creates cookie used with an Sso Identity to a user account /// /// /// /// /// /// public async Task CreateNewUserLinkCookie(HttpResponse response, AuditUserDetails auditUserDetails, GeneralIdRef generalIdRef, CancellationToken cancellationToken) { var guid = await _userManager.CreateSingleUseGuid(auditUserDetails, generalIdRef, cancellationToken); response.Cookies.Append(ssoNewUserLinkCookieName, guid.ToString(), new CookieOptions { HttpOnly = true, //Set True only the server side app needs to know about this SameSite = SameSiteMode.Lax, //Used when returning from an sso authorisation Secure = true, IsEssential = true, Expires = null, //Session Cookie Path = "/" }); } /// /// Used to find a profile link cookie and find the appropriate user account /// /// /// /// /// public async Task GetUserIdFromLinkCookie(HttpRequest request, CancellationToken cancellationToken) { var cookieContent = string.Empty; var cookieLink = new CookieLink() { LinkType = LinkType.None }; if (request.Cookies.ContainsKey(ssoProfileLinkCookieName)) { cookieContent = request.Cookies[ssoProfileLinkCookieName] ?? throw new NotFoundException(); cookieLink.LinkType = LinkType.Profile; } if (request.Cookies.ContainsKey(ssoNewUserLinkCookieName)) { cookieContent = request.Cookies[ssoNewUserLinkCookieName] ?? throw new NotFoundException(); cookieLink.LinkType = LinkType.NewUser; } if (cookieLink.LinkType == LinkType.None) { return null; } var guid = new Guid(cookieContent); cookieLink.User = await _userManager.GetUserWithSingleUseGuid(guid, cancellationToken); return cookieLink; } /// /// Delete any existing Profile link cookie. /// /// /// public Task DeleteLinkCookie(HttpResponse response) { response.Cookies.Delete(ssoProfileLinkCookieName); response.Cookies.Delete(ssoNewUserLinkCookieName); return Task.CompletedTask; } /// /// Find the SsoProvider Id using a cookie to save user input /// /// /// public Task GetSsoIdFromSsoIdCookie(HttpRequest request) { return Task.FromResult(request.Cookies.ContainsKey(ssoIdCookieName) ? request.Cookies[ssoIdCookieName].ToLong() : null); } /// /// Delete the SsoProvider cookie as the user has manually logged out /// /// /// public Task DeleteSsoIdCookie(HttpResponse response) { response.Cookies.Delete(ssoIdCookieName); return Task.CompletedTask; } /// /// Create the SsoProvider cookie, so that the login provess can be sped up for user convenience /// /// /// /// public Task CreateSsoIdCookie(HttpResponse response, long ssoId) { response.Cookies.Append(ssoIdCookieName, ssoId.ToString(), new CookieOptions() { HttpOnly = true, SameSite = SameSiteMode.Strict, Secure = true, IsEssential = true, Expires = DateTime.UtcNow.AddMonths(1), //cookie will expire after a month. Path = "/" }); return Task.CompletedTask; } }