using HRD.LDAPService.JWT;
using System;
using System.DirectoryServices.AccountManagement;
using System.Linq;
namespace HRD.LDAPService
{
public static class LdapAuthenticationService
{
private const string LDAP_DOMAIN = "dhr.local";
private static UserPrincipal GetUserPrincipal(string loginName, PrincipalContext principalContext)
{
try
{
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, loginName);
if (userPrincipal == null)
{
userPrincipal = UserPrincipal.FindByIdentity(principalContext, loginName);
if (userPrincipal == null)
{
throw new Exception($"Can't find an user by name: '{loginName}'");
}
}
return userPrincipal;
}
catch (Exception ex)
{
throw new Exception($"Login failed wrong user credentials '{loginName}'", ex);
}
}
///
/// Returns a User without LDAP user authentication
///
///
///
public static LdapUser RenewIdentity(string token)
{
if (string.IsNullOrEmpty(token)) { throw new ArgumentNullException("Token is empty!"); }
try
{
LdapUser ldapUserFromToken = JwtManager.DecryptTokenAsLdapUser(token);
if (ldapUserFromToken == default)
{
throw new Exception($"Wrong token");
}
using PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, LDAP_DOMAIN);
ldapUserFromToken.IsValidatCredentials = true;
UpdateLdapUserFromPrincipalContext(ref ldapUserFromToken, principalContext);
return ldapUserFromToken;
}
catch (Exception ex)
{
throw new Exception($"Renew failed", ex);
}
}
///
/// Returns a User without LDAP user authentication
///
///
///
public static LdapUser RenewIdentity(LdapUser ldapUser)
{
if (ldapUser == default) { return default; }
try
{
if (String.IsNullOrEmpty(ldapUser.LoginName))
{
throw new Exception($"Renew Login failed empty user Loginname");
}
LdapUser ldapUserFromToken = JwtManager.DecryptTokenAsLdapUser(ldapUser.Token);
if (ldapUserFromToken == default)
{
throw new Exception($"Wrong token");
}
if (!string.Equals(ldapUserFromToken.LoginName, ldapUser.LoginName, StringComparison.OrdinalIgnoreCase))
{
throw new Exception($"Loginname and Token-Loginname are not the same");
}
if (ldapUser.IsRealLDAPUser)
{
ldapUserFromToken.IsRealLDAPUser = ldapUser.IsRealLDAPUser;
using PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, LDAP_DOMAIN);
ldapUser.IsValidatCredentials = true;
UpdateLdapUserFromPrincipalContext(ref ldapUserFromToken, principalContext);
}
else
{
ldapUserFromToken.IsRealLDAPUser = false;
ldapUserFromToken.AddPasswordHash(ldapUser.PasswordHash);
if (!string.Equals(ldapUserFromToken.PasswordHashShort, ldapUser.PasswordHashShort, StringComparison.OrdinalIgnoreCase))
{
throw new Exception($"PasswordHashShort and Token-PasswordHashShortare not the same");
}
ldapUserFromToken.IsValidatCredentials = !string.IsNullOrEmpty(ldapUserFromToken.PasswordHash);
ldapUserFromToken.Enabled = ldapUserFromToken.IsValidatCredentials;
ldapUserFromToken.BadLogonCount = ldapUserFromToken.IsValidatCredentials ? 0 : ldapUserFromToken.BadLogonCount + 1;
//ldapUserFromToken.IsAccountLockedOut = ;
//ldapUserFromToken.LdapName = ;
//ldapUserFromToken.LdapSurname = ;
//ldapUserFromToken.LdapGuid = ;
//ldapUserFromToken.Email = ;
//ldapUserFromToken.AccountLockoutTime = ;
}
return ldapUserFromToken;
}
catch (Exception ex)
{
throw new Exception($"Login failed wrong user credentials '{ldapUser.LoginName}'", ex);
}
}
///
/// Returns a User after LDAP user authentication
///
///
///
public static bool CheckAndUpdateIdentityWithPassword(LdapUser ldapUser)
{
if (ldapUser == default) { return false; }
try
{
if (String.IsNullOrEmpty(ldapUser.LoginName))
{
throw new Exception($"Login failed wrong user Loginname");
}
if (!JwtTokenConfig.DeaktivateLDAP)
{
ldapUser.IsRealLDAPUser = true;
using var principalContext = new PrincipalContext(ContextType.Domain, LDAP_DOMAIN);
//Check PWD
ldapUser.IsValidatCredentials = principalContext.ValidateCredentials(ldapUser.LoginName, ldapUser.Password);
UpdateLdapUserFromPrincipalContext(ref ldapUser, principalContext);
}
else
{
ldapUser.IsRealLDAPUser = false;
//ldapUser.AddPasswordHash(JWTCrypt.GenerateHashPassword(ldapUser.Password));
var hash = JWTCrypt.SHA512(ldapUser.Password);
ldapUser.AddPasswordHash(hash);
ldapUser.IsValidatCredentials = !string.IsNullOrEmpty(ldapUser.PasswordHash);
if (ldapUser.IsValidatCredentials)
{
ldapUser.Enabled = true;
ldapUser.BadLogonCount = 0;
ldapUser.LastBadPasswordAttempt = null;
}
else
{
ldapUser.Enabled = false;
ldapUser.BadLogonCount = +1;
ldapUser.LastBadPasswordAttempt = DateTime.UtcNow;
}
//ldapUser.IsAccountLockedOut = ;
//ldapUser.LdapName = ;
//ldapUser.LdapSurname = ;
//ldapUser.LdapGuid = ;
//ldapUser.Email = ;
//ldapUser.AccountLockoutTime = ;
}
return true;
}
catch (Exception ex)
{
ldapUser.IsValidatCredentials = false;
throw new Exception($"Login failed wrong user credentials '{ldapUser.LoginName}'", ex);
}
}
private static void UpdateLdapUserFromPrincipalContext(ref LdapUser ldapUser, PrincipalContext principalContext)
{
UserPrincipal userPrincipal = GetUserPrincipal(ldapUser.LoginName, principalContext);
if (userPrincipal == default)
{
throw new Exception($"Renew Login failed wrong user credentials '{ldapUser.LoginName}'");
}
ldapUser.IsAccountLockedOut = userPrincipal.IsAccountLockedOut();
ldapUser.BadLogonCount = userPrincipal.BadLogonCount;
ldapUser.Enabled = userPrincipal.Enabled ?? false;
ldapUser.LastBadPasswordAttempt = userPrincipal.LastBadPasswordAttempt;
ldapUser.LdapName = userPrincipal.Name;
ldapUser.LdapSurname = userPrincipal.Surname;
ldapUser.LdapGuid = userPrincipal.Guid;
ldapUser.Email = userPrincipal.EmailAddress;
ldapUser.AccountLockoutTime = userPrincipal.AccountLockoutTime;
ldapUser.RoleList = ldapUser.RoleList.Union(JWT.JwtTokenConfig.JwtRoleList).ToList();
if (ldapUser.RoleList?.Count > 0)
{
ldapUser = userPrincipal.Context.CheckAndAddGroupMembers(userPrincipal, ldapUser);
}
}
}
}