Good day all, recently had to implement an Active Directory for our application and we have come across an InvalidCastException when trying to log into the site for the past few days I have been at our wits end trying to figure out what is causing this error. The code does seems to run fine as there are no errors when loading
LdapAuthentication.cs:
public abstract class LdapAuthenticationSource<TTenant, TUser> : DefaultExternalAuthenticationSource<TTenant, TUser>, ITransientDependency
where TTenant : AbpTenant<TUser>
where TUser : AbpUserBase, new()
{
/// <summary>
/// LDAP
/// </summary>
public const string SourceName = "LDAP";
public override string Name
{
get { return SourceName; }
}
private readonly ILdapSettings _settings;
private readonly IAbpZeroLdapModuleConfig _ldapModuleConfig;
protected LdapAuthenticationSource(ILdapSettings settings, IAbpZeroLdapModuleConfig ldapModuleConfig)
{
_settings = settings;
_ldapModuleConfig = ldapModuleConfig;
}
/// <inheritdoc/>
public override async Task<bool> TryAuthenticateAsync(string userNameOrEmailAddress, string plainPassword, TTenant tenant)
{
if (!_ldapModuleConfig.IsEnabled || !(await _settings.GetIsEnabled(GetIdOrNull(tenant))))
{
return false;
}
using (var principalContext = await CreatePrincipalContext(tenant))
{
return ValidateCredentials(principalContext, userNameOrEmailAddress, plainPassword);
}
}
/// <inheritdoc/>
public async override Task<TUser> CreateUserAsync(string userNameOrEmailAddress, TTenant tenant)
{
await CheckIsEnabled(tenant);
var user = await base.CreateUserAsync(userNameOrEmailAddress, tenant);
using (var principalContext = await CreatePrincipalContext(tenant))
{
var userPrincipal = UserPrincipal.FindByIdentity(principalContext, userNameOrEmailAddress);
if (userPrincipal == null)
{
throw new AbpException("Unknown LDAP user: " + userNameOrEmailAddress);
}
UpdateUserFromPrincipal(user, userPrincipal);
user.IsEmailConfirmed = true;
user.IsActive = true;
return user;
}
}
public async override Task UpdateUserAsync(TUser user, TTenant tenant)
{
await CheckIsEnabled(tenant);
await base.UpdateUserAsync(user, tenant);
using (var principalContext = await CreatePrincipalContext(tenant))
{
var userPrincipal = UserPrincipal.FindByIdentity(principalContext, user.UserName);
if (userPrincipal == null)
{
throw new AbpException("Unknown LDAP user: " + user.UserName);
}
UpdateUserFromPrincipal(user, userPrincipal);
}
}
protected virtual bool ValidateCredentials(PrincipalContext principalContext, string userNameOrEmailAddress, string plainPassword)
{
return principalContext.ValidateCredentials(userNameOrEmailAddress, plainPassword, ContextOptions.Negotiate);
}
protected virtual void UpdateUserFromPrincipal(TUser user, UserPrincipal userPrincipal)
{
user.UserName = userPrincipal.SamAccountName;
user.Name = userPrincipal.GivenName;
user.Surname = userPrincipal.Surname;
user.EmailAddress = userPrincipal.EmailAddress;
if (userPrincipal.Enabled.HasValue)
{
user.IsActive = userPrincipal.Enabled.Value;
}
}
protected virtual async Task<PrincipalContext> CreatePrincipalContext(TTenant tenant)
{
var tenantId = GetIdOrNull(tenant);
return new PrincipalContext(
await _settings.GetContextType(tenantId),
ConvertToNullIfEmpty(await _settings.GetDomain(tenantId)),
ConvertToNullIfEmpty(await _settings.GetContainer(tenantId)),
ConvertToNullIfEmpty(await _settings.GetUserName(tenantId)),
ConvertToNullIfEmpty(await _settings.GetPassword(tenantId))
);
}
private async Task CheckIsEnabled(TTenant tenant)
{
if (!_ldapModuleConfig.IsEnabled)
{
throw new AbpException("Ldap Authentication module is disabled globally!");
}
var tenantId = GetIdOrNull(tenant);
if (!await _settings.GetIsEnabled(tenantId))
{
throw new AbpException("Ldap Authentication is disabled for given tenant (id:" + tenantId + ")! You can enable it by setting '" + LdapSettingNames.IsEnabled + "' to true");
}
}
private static int? GetIdOrNull(TTenant tenant)
{
return tenant == null
? (int?)null
: tenant.Id;
}
private static string ConvertToNullIfEmpty(string str)
{
return str.IsNullOrWhiteSpace()
? null
: str;
}
}
}
LdapSettings.cs
public class LdapSettings: ILdapSettings, ITransientDependency
{
protected ISettingManager SettingManager { get; }
public LdapSettings(ISettingManager settingManager)
{
SettingManager = settingManager;
}
public virtual Task<bool> GetIsEnabled(int? tenantId)
{
return tenantId.HasValue
? SettingManager.GetSettingValueForTenantAsync<bool>(AppSettingNames.IsEnabled, tenantId.Value)
: SettingManager.GetSettingValueForApplicationAsync<bool>(AppSettingNames.IsEnabled);
}
public virtual async Task<ContextType> GetContextType(int? tenantId)
{
return tenantId.HasValue
? (await SettingManager.GetSettingValueForTenantAsync(AppSettingNames.ContextType, tenantId.Value)).ToEnum<ContextType>()
: (await SettingManager.GetSettingValueForApplicationAsync(AppSettingNames.ContextType)).ToEnum<ContextType>();
}
public virtual Task<string> GetContainer(int? tenantId)
{
return tenantId.HasValue
? SettingManager.GetSettingValueForTenantAsync(AppSettingNames.Container, tenantId.Value)
: SettingManager.GetSettingValueForApplicationAsync(AppSettingNames.Container);
}
public virtual Task<string> GetDomain(int? tenantId)
{
return tenantId.HasValue
? SettingManager.GetSettingValueForTenantAsync(AppSettingNames.Domain, tenantId.Value)
: SettingManager.GetSettingValueForApplicationAsync(AppSettingNames.Domain);
}
public virtual Task<string> GetUserName(int? tenantId)
{
return tenantId.HasValue
? SettingManager.GetSettingValueForTenantAsync(AppSettingNames.UserName, tenantId.Value)
: SettingManager.GetSettingValueForApplicationAsync(AppSettingNames.UserName);
}
public virtual Task<string> GetPassword(int? tenantId)
{
return tenantId.HasValue
? SettingManager.GetSettingValueForTenantAsync(AppSettingNames.Password, tenantId.Value)
: SettingManager.GetSettingValueForApplicationAsync(AppSettingNames.Password);
}
}
}
CoreModule.cs
[DependsOn(typeof(AbpZeroLdapModule))]
public class TestApp2020CoreModule : AbpModule
{
public override void PreInitialize()
{
Configuration.Auditing.IsEnabledForAnonymousUsers = true;
// Declare entity types
Configuration.Modules.Zero().EntityTypes.Tenant = typeof(Tenant);
Configuration.Modules.Zero().EntityTypes.Role = typeof(Role);
Configuration.Modules.Zero().EntityTypes.User = typeof(User);
TestApp2020LocalizationConfigurer.Configure(Configuration.Localization);
// Enable this line to create a multi-tenant application.
Configuration.MultiTenancy.IsEnabled = TestApp2020Consts.MultiTenancyEnabled;
// IocManager.Register<ILdapSettings, MyLdapSettings>(); //change default setting source
IocManager.Register<ILdapSettings, LdapSettings>();
Configuration.Modules.ZeroLdap().Enable(typeof(LdapSettings));
// Configure roles
AppRoleConfig.Configure(Configuration.Modules.Zero().RoleManagement);
Configuration.Settings.Providers.Add<AppSettingProvider>();
}
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(TestApp2020CoreModule).GetAssembly());
}
public override void PostInitialize()
{
IocManager.Resolve<AppTimes>().StartupTime = Clock.Now;
SettingManager settingsManager = IocManager.Resolve<SettingManager>();
settingsManager.ChangeSettingForApplication(AppSettingNames.IsEnabled, "true");
}
}
}
The application loads but the an error here prevents logging in
And this is what is showing in the logs
Any help would be greatly appreciated thanks.