Here is the Custom User Auth Repository
using System;
using System.DirectoryServices.AccountManagement;
using App.Interfaces;
using ServiceStack.Auth;
using System.Linq;
using System.Security.Principal;
using App.Security;
using ServiceStack;
using App.Logging;
using System.Threading.Tasks;
using System.Threading;
namespace App.Services
{
public class CustomUserAuthRepository : InMemoryAuthRepository
{
private readonly IDocumentManagerFactory _factory;
public CustomUserAuthRepository(IDocumentManagerFactory factory)
{
_factory = factory;
}
public override bool TryAuthenticate(string userName, string password, out IUserAuth userAuth)
{
var dm = _factory.GetDocumentManager(true);
var authenticator = new Authenticator(dm);
authenticator.Authenticate(userName, password);
var result = authenticator.Result;
userAuth = authenticator.UserAuth;
if (userAuth != null)
{
SaveUserAuth(userAuth);
if (result && authenticator.UserRole != null && authenticator.UserRole.RoleNames.Any())
userAuth.Roles.AddRange(authenticator.UserRole.RoleNames);
}
_factory.ReleaseDocumentManager(dm);
return result;
}
public override async Task<IUserAuth> TryAuthenticateAsync(string userName, string password, CancellationToken token = default)
{
var dm = _factory.GetDocumentManager(true);
var authenticator = new Authenticator(dm);
await authenticator.AuthenticateAsync(userName, password);
var result = authenticator.Result;
var userAuth = authenticator.UserAuth;
if (userAuth != null)
{
SaveUserAuth(userAuth);
if (result && authenticator.UserRole != null && authenticator.UserRole.RoleNames.Any())
userAuth.Roles.AddRange(authenticator.UserRole.RoleNames);
}
_factory.ReleaseDocumentManager(dm);
return userAuth;
}
private class Authenticator
{
private readonly IDocumentServicesProvider _service;
public Authenticator(IDocumentServicesProvider service)
{
_service = service;
}
public bool Result { get; private set; }
public CustomUserAuth UserAuth { get; private set; }
private User LoggedInUser { get; set; }
internal UserRole UserRole { get; set; }
private UserProfileData UserProfile { get; set; }
private WebUserProfile WebUserProfile { get; set; }
private WindowsIdentity Identity { get; set; }
private string SessionToken { get; set; }
public void Authenticate(string userName, string password)
{
Result = false;
UserAuth = null;
var isWindowsUser = userName.Contains('\\') || userName.Contains('@');
if (isWindowsUser)
{
LogonWindowsUser(userName, password);
return;
}
LogonCustomUser(userName, password);
if (!Result)
{
LogonWindowsUser(userName, password);
}
}
public async Task<UserAuth> AuthenticateAsync(string userName, string password)
{
Result = false;
UserAuth = null;
var isWindowsUser = userName.Contains('\\') || userName.Contains('@');
if (isWindowsUser)
{
await LogonWindowsUserAsync(userName, password);
return UserAuth;
}
await LogonCustomUserAsync(userName, password);
if (!Result)
{
await LogonWindowsUserAsync(userName, password);
}
return UserAuth;
}
private void LogonWindowsUser(string username, string password)
{
var token = IntPtr.Zero;
try
{
GetUserAndDomainNames(username, out username, out var domainName);
AdvApi.LogonUser(username, domainName, password, LogonType.NETWORK,
LogonProvider.DEFAULT, ref token);
if (token != IntPtr.Zero)
{
AdvApi.ImpersonateLoggedOnUser(token);
var user = WindowsUserNameHelper.GetUserPrincipalName();
var displayName = WindowsUserNameHelper.GetUserDisplayName();
if (string.IsNullOrEmpty(user))
user = WindowsUserNameHelper.GetUserName();
if (user != null)
{
LoggedInUser = new User(user)
{
Type = UserType.WindowsUser,
};
Identity = new WindowsIdentity(token);
AdvApi.RevertToSelf();
StartSession();
if (string.IsNullOrEmpty(SessionToken) && UserRole == null)
{
Result = false;
return;
}
UserAuth = new CustomUserAuth
{
UserName = user,
DisplayName = displayName,
Identity = Identity,
SessionId = SessionToken,
User = LoggedInUser,
Role = UserRole,
UserProfile = UserProfile,
WebUserProfile=WebUserProfile,
ShortUserName = Environment.UserName,
ClientAppName = Session.ClientAppName,
ClientApp = Session.ClientApp
};
try
{
UserAuth.Email = UserPrincipal.Current.EmailAddress;
}
catch (Exception ex)
{
if (UserAuth.Email == null)
{
UserAuth.Email = "";
}
LogMain.Main.LogException(ex);
}
Result = true;
}
}
else
{
Result = false;
}
}
finally
{
if (token != IntPtr.Zero)
{
AdvApi.CloseHandle(token);
AdvApi.RevertToSelf();
}
}
}
private async Task LogonWindowsUserAsync(string username, string password)
{
var token = IntPtr.Zero;
try
{
GetUserAndDomainNames(username, out username, out var domainName);
await Task.Run(() => AdvApi.LogonUser(username, domainName, password, LogonType.NETWORK,
LogonProvider.DEFAULT, ref token));
if (token != IntPtr.Zero)
{
AdvApi.ImpersonateLoggedOnUser(token);
var user = WindowsUserNameHelper.GetUserPrincipalName();
var displayName = WindowsUserNameHelper.GetUserDisplayName();
if (string.IsNullOrEmpty(user))
user = WindowsUserNameHelper.GetUserName();
if (user != null)
{
LoggedInUser = new User(user)
{
Type = UserType.WindowsUser,
};
Identity = new WindowsIdentity(token);
AdvApi.RevertToSelf();
StartSession();
if (string.IsNullOrEmpty(SessionToken) && UserRole == null)
{
Result = false;
return;
}
UserAuth = new CustomUserAuth
{
UserName = user,
DisplayName = displayName,
Identity = Identity,
SessionId = SessionToken,
User = LoggedInUser,
Role = UserRole,
UserProfile = UserProfile,
WebUserProfile = WebUserProfile,
ShortUserName = Environment.UserName,
ClientAppName = Session.ClientAppName,
ClientApp = Session.ClientApp
};
try
{
UserAuth.Email = UserPrincipal.Current.EmailAddress;
}
catch (Exception ex)
{
if (UserAuth.Email == null)
{
UserAuth.Email = "";
}
LogMain.Main.LogException(ex);
}
Result = true;
}
}
else
{
Result = false;
}
}
finally
{
if (token != IntPtr.Zero)
{
AdvApi.CloseHandle(token);
AdvApi.RevertToSelf();
}
}
}
private void GetUserAndDomainNames(string value, out string userName, out string domainName)
{
if (value.Contains("@"))
{
var parts = value.Split('@');
userName = parts[0];
domainName = parts[1];
return;
}
if (value.Contains("\\"))
{
var parts = value.Split('\\');
domainName = parts[0];
userName = parts[1];
return;
}
userName = value;
domainName = GeneralHelper.GetDomainName();
}
private void LogonCustomUser(string userName, string password)
{
var ud = new UserDescriptor {UserName = userName, PasswordString = password};
ud.HashPassword();
if (!ResultCode.Succeeded(_service.GetUser(ref ud)))
{
return;
}
LoggedInUser = new User(userName) {Type = UserType.CustomUser};
StartSession();
if (string.IsNullOrEmpty(SessionToken) && UserRole == null)
{
Result = false;
return;
}
UserAuth = new CustomUserAuth
{
UserName = ud.UserName,
DisplayName = ud.FullName,
SessionId = SessionToken,
User = LoggedInUser,
Role = UserRole,
DRUser = ud,
UserProfile = UserProfile,
WebUserProfile=WebUserProfile,
ShortUserName = ud.UserName,
ClientApp = Session.ClientApp,
ClientAppName = Session.ClientAppName,
Email = ud.Email
};
Result = true;
}
private async Task LogonCustomUserAsync(string userName, string password)
{
var ud = new UserDescriptor { UserName = userName, PasswordString = password };
ud.HashPassword();
var retVal = await Task.Run(() => _service.GetUser(ref ud));
if (!ResultCode.Succeeded(retVal))
{
return;
}
LoggedInUser = new User(userName) { Type = UserType.CustomUser };
StartSession();
if (string.IsNullOrEmpty(SessionToken) && UserRole == null)
{
Result = false;
return;
}
UserAuth = new CustomUserAuth
{
UserName = ud.UserName,
DisplayName = ud.FullName,
SessionId = SessionToken,
User = LoggedInUser,
Role = UserRole,
DRUser = ud,
UserProfile = UserProfile,
WebUserProfile = WebUserProfile,
ShortUserName = ud.UserName,
ClientApp = Session.ClientApp,
ClientAppName = Session.ClientAppName,
Email = ud.Email
};
Result = true;
}
private void StartSession()
{
var nameDs = Role.GetUserRoleDs(LoggedInUser, true, Identity);
Session.User = LoggedInUser.Name;
LogMain.Main.LogDebug($"StartSession - User:{Session.User}; ClientApp:{Session.ClientApp}");
if (Session.ClientApp.IsNullOrEmpty())
{
Session.ClientApp = "App API";
}
var rval = _service.StartSession(nameDs, out var userRole, out var userProfile, out var webuserProfile);
if (!ResultCode.Succeeded(rval))
{
return;
}
if (userRole != null) UserRole = userRole;
if (userProfile != null) UserProfile = userProfile;
if (webuserProfile != null) WebUserProfile = webuserProfile;
SessionToken = Session.ID;
}
}
}
}