diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..95482f8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,93 @@ +root = true + +# ========================================================= +# GLOBAL DEFAULTS (apply to all files) +# ========================================================= +[*] +indent_style = space +indent_size = 4 +tab_width = 4 +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +# ========================================================= +# C# (Visual Studio, .NET APIs, microservices) +# ========================================================= +[*.cs] +indent_style = space +indent_size = 4 +dotnet_sort_system_directives_first = true +csharp_new_line_before_open_brace = all + +# ========================================================= +# Java (Spring Boot microservices, shared libs) +# ========================================================= +[*.java] +indent_style = space +indent_size = 4 + +# ========================================================= +# Python (ML scripts, utilities, automation) +# ========================================================= +[*.py] +indent_style = space +indent_size = 4 +max_line_length = 120 + +# ========================================================= +# JavaScript / TypeScript (React, Angular) +# ========================================================= +[*.js] +indent_size = 2 + +[*.jsx] +indent_size = 2 + +[*.ts] +indent_size = 2 + +[*.tsx] +indent_size = 2 + +# ========================================================= +# HTML / CSS / SCSS (UI templates) +# ========================================================= +[*.html] +indent_size = 2 + +[*.css] +indent_size = 2 + +[*.scss] +indent_size = 2 + +# ========================================================= +# JSON / YAML / XML (configs, pipelines, manifests) +# ========================================================= +[*.json] +indent_size = 2 + +[*.yml] +indent_size = 2 + +[*.yaml] +indent_size = 2 + +[*.xml] +indent_size = 2 + +# ========================================================= +# Dockerfiles +# ========================================================= +[Dockerfile] +indent_style = space +indent_size = 4 + +# ========================================================= +# Shell scripts +# ========================================================= +[*.sh] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1f99a5a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,47 @@ +name: CI + +on: + push: + pull_request: + merge_group: + workflow_dispatch: + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-test: + runs-on: ubuntu-latest + env: + DOTNET_NOLOGO: true + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + + steps: + - uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 10.0.x + cache: true + cache-dependency-path: | + **/*.csproj + **/*.fsproj + **/*.props + **/*.targets + **/nuget.config + global.json + Directory.Packages.props + + - name: dotnet info + run: dotnet --info + + - name: Restore + run: dotnet restore Bitai.Ldap.Helper.sln + + - name: Build + run: dotnet build Bitai.Ldap.Helper.sln --configuration Release --no-restore + + - name: Test + run: dotnet test Bitai.Ldap.Helper.sln --configuration Release --no-build --no-restore --verbosity normal diff --git a/LDAP Helper Libraries.sln b/Bitai.Ldap.Helper.sln similarity index 99% rename from LDAP Helper Libraries.sln rename to Bitai.Ldap.Helper.sln index 16c2481..2e4c7c0 100644 --- a/LDAP Helper Libraries.sln +++ b/Bitai.Ldap.Helper.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.4.33213.308 +# Visual Studio Version 18 +VisualStudioVersion = 18.6.11822.322 stable MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bitai.LDAPHelper.DTO", "src\Bitai.LDAPHelper.DTO\Bitai.LDAPHelper.DTO.csproj", "{2386A126-F237-43FD-9A7C-FDF6718ACAD7}" EndProject diff --git a/README.md b/README.md index 4aa6a98..fa967d7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Bitai.LDAPHelper ![Logo](resources/hierarchy_32.png) -A high-performance **.NET 8.0** library wrapping **Novell.Directory.Ldap.NETStandard** functionality to interact with LDAP-compliant Directory Services (such as Microsoft Active Directory). It simplifies operations like searching, authenticating users, and creating, modifying, disabling, or deleting accounts. +A high-performance library wrapping **Novell.Directory.Ldap.NETStandard** functionality to interact with LDAP-compliant Directory Services (such as Microsoft Active Directory). It simplifies operations like searching, authenticating users, and creating, modifying, disabling, or deleting accounts. This library is a key component of the [Bitai.LDAPWebApi](https://github.com/bitai-cs/LDAPWebApi) solution ecosystem. @@ -12,16 +12,16 @@ The library is organized into specialized helper classes targeting specific dire ### 🛡️ 1. Authentication (`Authenticator`) Enables quick and secure validation of user credentials on the LDAP/AD server. -- Supports both **User Distinguished Name (DN)** (`LDAPDistinguishedNameCredential`) and **Domain Account Name** (`LDAPDomainAccountCredential`) credential structures. +- Supports both **User Distinguished Name (DN)** (`LDAPDistinguishedNameCredential`) and **Domain Username** (`LDAPDomainAccountCredential`) credential structures. - Provides a simple authentication bind check (`AuthenticateAsync(credential)`). - Provides a comprehensive, pre-validated authentication workflow that first searches the user entry in Active Directory to ensure uniqueness and validity before attempting the bind (`AuthenticateAsync(credential, searchLimits, searchCredential)`). ### 👤 2. Account Management (`AccountManager`) Simplifies user provisioning and lifecycle management within Active Directory. -- **Create User Accounts** (`CreateUserAccountForMsAD`): Provision new Active Directory entries (`LDAPMsADUserAccount`) with extensive attribute mappings (such as UPN, sAMAccountName, unicodePwd, department, memberOf, object classes, and user control flags). +- **Create MS AD User Accounts** (`CreateUserAccountForMsAD`): Provision new Active Directory entries (`LDAPMsADUserAccount`) with extensive attribute mappings (such as UPN, sAMAccountName, unicodePwd, department, memberOf, object classes, and user control flags). - **Set/Change Passwords** (`SetUserAccountPasswordForMsAD`): Safe password replacement utilizing secure Unicode encoding. It can optionally test immediate post-update authentication. -- **Disable Accounts** (`DisableUserAccountForMsAD`): Securely disables accounts by updating the `userAccountControl` attribute with the `ACCOUNTDISABLE` flag, dynamically preserving all other existing account flags to prevent unintended configuration loss. -- **Remove Accounts** (`RemoveUserAccountForMsAD`): Permanently deletes user entries from the directory service. +- **Disable MS AD Accounts** (`DisableUserAccountForMsAD`): Securely disables accounts by updating the `userAccountControl` attribute with the `ACCOUNTDISABLE` flag, dynamically preserving all other existing account flags to prevent unintended configuration loss. +- **Remove MS AD Accounts** (`RemoveUserAccountForMsAD`): Permanently deletes user entries from the directory service. ### 🔍 3. Directory Searching (`Searcher`) Facilitates fast, flexible searching using highly customizable LDAP search configurations. @@ -49,7 +49,7 @@ The solution `LDAP Helper Libraries.sln` consists of the following projects: ## ⚙️ Requirements & Dependencies -- **.NET 8.0 SDK** or higher. +- **.NET 10 SDK** or higher. - **Novell.Directory.Ldap.NETStandard** (v4.0.0+) package dependency. --- diff --git a/demo/Bitai.LDAPHelper.Demo/Bitai.LDAPHelper.Demo.csproj b/demo/Bitai.LDAPHelper.Demo/Bitai.LDAPHelper.Demo.csproj index 784525c..7189504 100644 --- a/demo/Bitai.LDAPHelper.Demo/Bitai.LDAPHelper.Demo.csproj +++ b/demo/Bitai.LDAPHelper.Demo/Bitai.LDAPHelper.Demo.csproj @@ -1,7 +1,7 @@  Exe - net8.0 + net10.0 Bitai.LDAPHelper.Demo Viko Bastidas (BITAI) BITAI @@ -10,17 +10,17 @@ © 2026 BITAI. All rights reserved. Bitai.Bitai.LDAPHelper.Demo hierarchy_32.png - 8.6.0 - 8.6.0.0 - 8.6.0.0 - .NET 8 ready + 10.0.0 + 10.0.0 + 10.0.0 + .NET 10 ready ldap-ad-identity-auth-openid-oauth-security - - - - + + + + diff --git a/demo/Bitai.LDAPHelper.Demo/Program.DemoMethods.cs b/demo/Bitai.LDAPHelper.Demo/Program.DemoMethods.cs index ad1f854..168821c 100644 --- a/demo/Bitai.LDAPHelper.Demo/Program.DemoMethods.cs +++ b/demo/Bitai.LDAPHelper.Demo/Program.DemoMethods.cs @@ -23,7 +23,7 @@ public static async Task Demo_Authenticator_Authenticate_Simple(DemoContext cont var domainAccountCredentialParts = domainAccountCredential.Split(new char[] { '\\' }); - Log.Information("Authenticating account name..."); + Log.Information("Authenticating domain username..."); var authenticationResult = await authenticator.AuthenticateAsync( new LDAPDomainAccountCredential(domainAccountCredentialParts[0], domainAccountCredentialParts[1], accountPassword), context.RequestLabel); @@ -33,9 +33,9 @@ public static async Task Demo_Authenticator_Authenticate_Simple(DemoContext cont Log.Information("{@model}", authenticationResult); if (authenticationResult.IsAuthenticated) - Log.Information("Account name authenticated."); + Log.Information("Username authenticated."); else - Log.Warning("Account name NOT authenticated."); + Log.Warning("Username NOT authenticated."); } else { @@ -58,7 +58,7 @@ public static async Task Demo_Authenticator_Authenticate_WithAccountValidation(D var domainAccountCredentialParts = domainAccountCredential.Split(new char[] { '\\' }); - Log.Information("Authenticating account name with account validation..."); + Log.Information("Authenticating username with account validation..."); var authenticationResult = await authenticator.AuthenticateAsync( new LDAPDomainAccountCredential(domainAccountCredentialParts[0], domainAccountCredentialParts[1], accountPassword), context.GetSearchLimits(), @@ -70,9 +70,9 @@ public static async Task Demo_Authenticator_Authenticate_WithAccountValidation(D Log.Information("{@model}", authenticationResult); if (authenticationResult.IsAuthenticated) - Log.Information("Account name authenticated."); + Log.Information("Username authenticated."); else - Log.Warning("Account name NOT authenticated."); + Log.Warning("Username NOT authenticated."); } else { @@ -488,4 +488,4 @@ public static async Task Demo_GroupMembershipValidator_CheckGroupMembership( } #endregion -} \ No newline at end of file +} diff --git a/src/Bitai.LDAPHelper.DTO/Bitai.LDAPHelper.DTO.csproj b/src/Bitai.LDAPHelper.DTO/Bitai.LDAPHelper.DTO.csproj index e268b80..a77f921 100644 --- a/src/Bitai.LDAPHelper.DTO/Bitai.LDAPHelper.DTO.csproj +++ b/src/Bitai.LDAPHelper.DTO/Bitai.LDAPHelper.DTO.csproj @@ -1,10 +1,10 @@ - net8.0 - 8.6.0.0 - 8.6.0.0 - 8.6.0 + net10.0 + 10.0.0 + 10.0.0 + 10.0.0 Bitai.LDAPHelper.DTO true Viko Bastidas (BITAI) @@ -21,7 +21,7 @@ GitHub ldap, authentication, directory, helper README.md - .NET 8 ready + .NET 10 ready diff --git a/src/Bitai.LDAPHelper.DTO/LDAPDistinguishedNameCredential.cs b/src/Bitai.LDAPHelper.DTO/LDAPDistinguishedNameCredential.cs index c33d969..3e60aeb 100644 --- a/src/Bitai.LDAPHelper.DTO/LDAPDistinguishedNameCredential.cs +++ b/src/Bitai.LDAPHelper.DTO/LDAPDistinguishedNameCredential.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -32,7 +32,7 @@ public LDAPDistinguishedNameCredential() public LDAPDistinguishedNameCredential(string distinguishedName, string password) { if (string.IsNullOrEmpty(distinguishedName)) - throw new InvalidOperationException("The account name must be specified."); + throw new InvalidOperationException("A distinguished name is required: the account’s DN must be specified."); DistinguishedName = distinguishedName; Password = password; diff --git a/src/Bitai.LDAPHelper.DTO/LDAPDomainAccountCredential.cs b/src/Bitai.LDAPHelper.DTO/LDAPDomainAccountCredential.cs index d2541dc..a2626d3 100644 --- a/src/Bitai.LDAPHelper.DTO/LDAPDomainAccountCredential.cs +++ b/src/Bitai.LDAPHelper.DTO/LDAPDomainAccountCredential.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; @@ -28,21 +28,21 @@ public LDAPDomainAccountCredential() /// /// Constructor /// - /// Domain name. - /// Account name. + /// Domain name + /// Username /// Account password. /// Constructor exception. - public LDAPDomainAccountCredential(string domainName, string accountName, string domainAccountPassword) + public LDAPDomainAccountCredential(string domainName, string username, string domainAccountPassword) { if (string.IsNullOrEmpty(domainName)) throw new InvalidOperationException("The domain name must be specified."); - if (string.IsNullOrEmpty(accountName)) - throw new InvalidOperationException("The account name must be specified."); + if (string.IsNullOrEmpty(username)) + throw new InvalidOperationException("The username must be specified."); DomainName = domainName; - AccountName = accountName; + AccountName = username; DomainAccountPassword = domainAccountPassword; } diff --git a/src/Bitai.LDAPHelper/AccountManager.cs b/src/Bitai.LDAPHelper/AccountManager.cs index f22809f..7657a0e 100644 --- a/src/Bitai.LDAPHelper/AccountManager.cs +++ b/src/Bitai.LDAPHelper/AccountManager.cs @@ -30,11 +30,11 @@ public void InitializeMissingMsADUserAccountDN(LDAPMsADUserAccount userAccount) } /// - /// Create a user account in MS Active Directory service + /// Create a username in MS Active Directory service /// https://www.rlmueller.net/Name_Attributes.htm /// /// - /// DN of the container in which the user account will be created. + /// DN of the container in which the username will be created. /// Optional tag to mark the request and/or response. /// A Task of public async Task CreateUserAccountForMsAD(LDAPMsADUserAccount newUserAccount, string requestLabel = null) @@ -58,7 +58,7 @@ public async Task CreateUserAccountForMsAD(LDAP throw new InvalidOperationException($"{nameof(newUserAccount.ObjectClass)} is required."); #endregion - //Generate user account DistinguishedName LDAP attribute + //Generate username DistinguishedName LDAP attribute InitializeMissingMsADUserAccountDN(newUserAccount); using (var ldapConnection = await GetLdapConnection(this.ConnectionInfo, this.DomainAccountCredential)) { @@ -113,18 +113,18 @@ public async Task CreateUserAccountForMsAD(LDAP } #endregion - //Add new user account entry to the directory + //Add new username entry to the directory await ldapConnection.AddEntryAsync(newUserAccount.DistinguishedName, attributeSet); } return new LDAPCreateMsADUserAccountResult(newUserAccount.SecureClone(), requestLabel) { - OperationMessage = $"User account created at {newUserAccount.DistinguishedName} with {EntryAttribute.sAMAccountName.ToString()}: {newUserAccount.SAMAccountName}" + OperationMessage = $"MS AD user account created at {newUserAccount.DistinguishedName} with {EntryAttribute.sAMAccountName.ToString()}: {newUserAccount.SAMAccountName}" }; } catch (Exception ex) { - return new LDAPCreateMsADUserAccountResult("Error creating user account.", ex, requestLabel) + return new LDAPCreateMsADUserAccountResult("Error creating username.", ex, requestLabel) { UserAccount = newUserAccount.SecureClone() }; @@ -132,18 +132,18 @@ public async Task CreateUserAccountForMsAD(LDAP } /// - /// Set a password for a user account in MS Active Directory service. This method will verify the authenticity of the user account by its distinguished name before trying to set the password. If the user account is not valid, the operation will not be attempted and an error will be returned. + /// Set a password for a username in MS Active Directory service. This method will verify the authenticity of the username by its distinguished name before trying to set the password. If the username is not valid, the operation will not be attempted and an error will be returned. /// /// /// Optional tag to mark the request and/or response. - /// True if the account will be tested to be able to authenticate with the new password. False if only the password will be assigned, authentication will not be tested. + /// True if the MS AD user account will be tested to verify authentication with the new password. False if the password will simply be assigned and authentication will not be tested. /// public async Task SetUserAccountPasswordForMsAD(DTO.LDAPDistinguishedNameCredential credential, string requestLabel = null, bool postUpdateTestAuthentication = true) { try { if (string.IsNullOrEmpty(credential.DistinguishedName)) - throw new ArgumentNullException("The distinguished name of the user account is required."); + throw new ArgumentNullException("The distinguished name of the username is required."); if (string.IsNullOrEmpty(credential.Password)) throw new ArgumentNullException($"The password to be assigned is required."); @@ -203,9 +203,9 @@ DTO.LDAPPasswordUpdateResult createSuccessfulResult(string label, string name) { } /// - /// Remove a user account from MS Active Directory service. This method will verify the authenticity of the user account by its distinguished name before trying to remove it. If the user account is not valid, the operation will not be attempted and an error will be returned. + /// Remove a username from MS Active Directory service. This method will verify the authenticity of the username by its distinguished name before trying to remove it. If the username is not valid, the operation will not be attempted and an error will be returned. /// - /// User account distinguished name + /// Distinguished name of the username /// Optional tag to mark the request and/or response. /// public async Task DisableUserAccountForMsAD(string distinguishedName, string requestLabel) @@ -218,7 +218,7 @@ public async Task DisableUserAccountForMs var entry = await verifyUserAccountAuthenticity(distinguishedName, requestLabel); using (var ldapConnection = await GetLdapConnection(this.ConnectionInfo, this.DomainAccountCredential)) { - //To disable a user account in MS AD, the userAccountControl attribute needs to be set with the appropriate flags. The flag for disabling an account is ACCOUNTDISABLE (0x0002). However, when setting the userAccountControl attribute, it is important to preserve the existing flags that are set for the account, and only add the ACCOUNTDISABLE flag without removing any of the existing flags. This is because other flags may be set for the account that are necessary for its proper functioning, and removing them could cause unintended consequences. Therefore, when disabling a user account, you should retrieve the current value of the userAccountControl attribute, add the ACCOUNTDISABLE flag to it, and then update the attribute with the new value that includes both the existing flags and the ACCOUNTDISABLE flag. + //To disable a MS AD user account, the userAccountControl attribute needs to be set with the appropriate flags. The flag for disabling an account is ACCOUNTDISABLE (0x0002). However, when setting the userAccountControl attribute, it is important to preserve the existing flags that are set for the account, and only add the ACCOUNTDISABLE flag without removing any of the existing flags. This is because other flags may be set for the account that are necessary for its proper functioning, and removing them could cause unintended consequences. Therefore, when disabling a username, you should retrieve the current value of the userAccountControl attribute, add the ACCOUNTDISABLE flag to it, and then update the attribute with the new value that includes both the existing flags and the ACCOUNTDISABLE flag. UserAccountControlFlagsForMsAD userAccountControlFlags = UserAccountControlFlagsForMsAD.NORMAL_ACCOUNT | UserAccountControlFlagsForMsAD.ACCOUNTDISABLE; //var userAccountControlAttribute = new LdapAttribute(DTO.EntryAttribute.userAccountControl.ToString(), ((int)userAccountControlFlags).ToString()); @@ -234,7 +234,7 @@ public async Task DisableUserAccountForMs return new DTO.LDAPDisableUserAccountOperationResult(requestLabel) { - OperationMessage = $"User account {entry.samAccountName} has been disabled." + OperationMessage = $"Username {entry.samAccountName} has been disabled." }; } catch (Bitai.LDAPHelper.EntryNotFoundException ex) { @@ -242,14 +242,14 @@ public async Task DisableUserAccountForMs } catch (Exception ex) { - return new LDAPDisableUserAccountOperationResult($"Error trying to disable user account with DN: {distinguishedName}", ex, requestLabel); + return new LDAPDisableUserAccountOperationResult($"Error trying to disable username with DN: {distinguishedName}", ex, requestLabel); } } /// - /// Remove a user account in MS Active Directory service. This operation will permanently delete the user account entry from the directory, so it should be used with caution. + /// Remove a username in MS Active Directory service. This operation will permanently delete the username entry from the directory, so it should be used with caution. /// - /// User account distinguished name. + /// Distinguished name of the username /// Optional tag to mark the request and/or response. /// public async Task RemoveUserAccountForMsAD(string distinguishedName, string requestLabel = null) @@ -257,20 +257,20 @@ public async Task RemoveUserAccountForMsAD(stri try { if (string.IsNullOrEmpty(distinguishedName)) - throw new ArgumentNullException("The DN of the account to be removed must be provided."); + throw new ArgumentNullException("The distinguished name of the username to remove must be provided."); var entry = await verifyUserAccountAuthenticity(distinguishedName, requestLabel); using (var ldapConnection = await GetLdapConnection(this.ConnectionInfo, this.DomainAccountCredential)) { - //To remove a user account from MS AD, the user account entry needs to be deleted from the directory. This operation will permanently delete the user account entry, so it should be used with caution. + //To remove a username from MS AD, the username entry needs to be deleted from the directory. This operation will permanently delete the username entry, so it should be used with caution. await ldapConnection.DeleteEntryAsync(entry.distinguishedName); //await ldapConnection.DeleteAsync(entry.distinguishedName); } return new LDAPRemoveMsADUserAccountResult(requestLabel) { - OperationMessage = $"The user account {entry.samAccountName} has been successfully removed." + OperationMessage = $"The username {entry.samAccountName} has been successfully removed." }; } catch (Bitai.LDAPHelper.EntryNotFoundException ex) { @@ -278,7 +278,7 @@ public async Task RemoveUserAccountForMsAD(stri } catch (Exception ex) { - return new LDAPRemoveMsADUserAccountResult($"Error trying to remove user account with DN: {distinguishedName}", ex, requestLabel); + return new LDAPRemoveMsADUserAccountResult($"Error trying to remove username with DN: {distinguishedName}", ex, requestLabel); } } @@ -307,7 +307,7 @@ private async Task verifyUserAccountAuthenticity(string distinguished var entry = searchResult.Entries.Single(); if (!entry.objectClass.Contains("user")) - throw new InvalidOperationException($"DN {distinguishedName} is not a user account."); + throw new InvalidOperationException($"DN {distinguishedName} is not a username."); return entry; } diff --git a/src/Bitai.LDAPHelper/Authenticator.cs b/src/Bitai.LDAPHelper/Authenticator.cs index 0a5d4c9..6d2e64c 100644 --- a/src/Bitai.LDAPHelper/Authenticator.cs +++ b/src/Bitai.LDAPHelper/Authenticator.cs @@ -1,4 +1,4 @@ -using Bitai.LDAPHelper.LdapAdapters; +using Bitai.LDAPHelper.LdapAdapters; using Bitai.LDAPHelper.DTO; using Bitai.LDAPHelper.QueryFilters; using System; @@ -42,7 +42,7 @@ public Authenticator(ConnectionInfo connectionInfo, ILdapConnectionFactoryAdapte else { if (searchResult.Entries.Count() == 0) { authenticationResult = new LDAPDomainAccountAuthenticationResult(credential.SecureClone(), false, requestLabel); - authenticationResult.SetSuccessfulOperation($"The domain user account {credential.DomainName}\\{credential.AccountName} could not be found."); + authenticationResult.SetSuccessfulOperation($"The domain username {credential.DomainName}\\{credential.AccountName} could not be found."); return authenticationResult; } @@ -64,7 +64,7 @@ public Authenticator(ConnectionInfo connectionInfo, ILdapConnectionFactoryAdapte authenticationResult = new DTO.LDAPDomainAccountAuthenticationResult(credential.SecureClone(), authenticated.Value, requestLabel); if (authenticated.Value) - authenticationResult.SetSuccessfulOperation($"The domain user account {credential.DomainName}\\{credential.AccountName} has been successfully authenticated."); + authenticationResult.SetSuccessfulOperation($"The domain username {credential.DomainName}\\{credential.AccountName} has been successfully authenticated."); else authenticationResult.SetSuccessfulOperation("The password is wrong"); @@ -93,9 +93,9 @@ public Authenticator(ConnectionInfo connectionInfo, ILdapConnectionFactoryAdapte var result = new DTO.LDAPDomainAccountAuthenticationResult(credential.SecureClone(), authenticated.Value, requestLabel); if (authenticated.Value) - result.SetSuccessfulOperation($"The domain user account {credential.DomainAccountName} has been successfully authenticated."); + result.SetSuccessfulOperation($"The domain username {credential.DomainAccountName} has been successfully authenticated."); else - result.SetSuccessfulOperation("Wrong user account and/or password."); + result.SetSuccessfulOperation("Wrong username and/or password."); return result; } @@ -130,7 +130,7 @@ public Authenticator(ConnectionInfo connectionInfo, ILdapConnectionFactoryAdapte else { if (searchResult.Entries.Count() == 0) { authenticationResult = new LDAPDistinguishedNameAuthenticationResult(credential.SecureClone(), false, requestLabel); - authenticationResult.SetSuccessfulOperation($"The account {credential.DistinguishedName} could not be found."); + authenticationResult.SetSuccessfulOperation($"Unable to locate the account's DN: {credential.DistinguishedName}"); return authenticationResult; } @@ -152,9 +152,9 @@ public Authenticator(ConnectionInfo connectionInfo, ILdapConnectionFactoryAdapte authenticationResult = new DTO.LDAPDistinguishedNameAuthenticationResult(credential.SecureClone(), authenticated.Value, requestLabel); if (authenticated.Value) - authenticationResult.SetSuccessfulOperation($"The account {credential.DistinguishedName} has been successfully authenticated."); + authenticationResult.SetSuccessfulOperation($"The account with DN: {credential.DistinguishedName} has been successfully authenticated."); else - authenticationResult.SetSuccessfulOperation("The password is wrong"); + authenticationResult.SetSuccessfulOperation("Authentication failed: incorrect password."); return authenticationResult; } @@ -176,9 +176,9 @@ public Authenticator(ConnectionInfo connectionInfo, ILdapConnectionFactoryAdapte var result = new DTO.LDAPDistinguishedNameAuthenticationResult(credential.SecureClone(), authenticated.Value, requestLabel); if (authenticated.Value) - result.SetSuccessfulOperation($"The account {credential.DistinguishedName} has been successfully authenticated."); + result.SetSuccessfulOperation($"The account with DN: {credential.DistinguishedName} has been successfully authenticated."); else - result.SetSuccessfulOperation("Wrong account and/or password."); + result.SetSuccessfulOperation("Authentication failed: incorrect username or password."); return result; } @@ -188,4 +188,4 @@ public Authenticator(ConnectionInfo connectionInfo, ILdapConnectionFactoryAdapte } #endregion } -} \ No newline at end of file +} diff --git a/src/Bitai.LDAPHelper/Bitai.LDAPHelper.csproj b/src/Bitai.LDAPHelper/Bitai.LDAPHelper.csproj index 8679c0f..833e4ce 100644 --- a/src/Bitai.LDAPHelper/Bitai.LDAPHelper.csproj +++ b/src/Bitai.LDAPHelper/Bitai.LDAPHelper.csproj @@ -1,16 +1,16 @@ - net8.0 + net10.0 Viko Bastidas (BITAI) BITAI LDAP Services Wrappers Library to wrap Novell.Directory.Ldap.NETStandard functionality to make LDAP common queries to search accounts and objects in a Directory Service. © 2026 BITAI. All rights reserved. - 8.6.0 - 8.6.0.0 + 10.0.0 + 10.0.0 hierarchy_32.png - 8.6.0.0 + 10.0.0 true Bitai.LDAPHelper Bitai.LDAPHelper @@ -20,7 +20,7 @@ ldap;authentication;authorization;directory;helper;oauth;openid;ad;security;identity LICENSE.md Bitai.LDAPHelper - .NET 8 ready + .NET 10 ready README.md diff --git a/tests/Bitai.LDAPHelper.Tests.Mocks/Bitai.LDAPHelper.Tests.Mocks.csproj b/tests/Bitai.LDAPHelper.Tests.Mocks/Bitai.LDAPHelper.Tests.Mocks.csproj index e76fde5..f554382 100644 --- a/tests/Bitai.LDAPHelper.Tests.Mocks/Bitai.LDAPHelper.Tests.Mocks.csproj +++ b/tests/Bitai.LDAPHelper.Tests.Mocks/Bitai.LDAPHelper.Tests.Mocks.csproj @@ -1,12 +1,12 @@  - net8.0 + net10.0 enable enable - 8.6.0 - 8.6.0.0 - 8.6.0.0 + 10.0.0 + 10.0.0 + 10.0.0 Viko Bastidas (BITAI) © 2026 BITAI. All rights reserved. https://github.com/bitai-cs/LDAPHelper.git diff --git a/tests/Bitai.LDAPHelper.Tests/AccountManagerAdapterTests.cs b/tests/Bitai.LDAPHelper.Tests/AccountManagerAdapterTests.cs index d36efe3..fbe8f50 100644 --- a/tests/Bitai.LDAPHelper.Tests/AccountManagerAdapterTests.cs +++ b/tests/Bitai.LDAPHelper.Tests/AccountManagerAdapterTests.cs @@ -1,4 +1,4 @@ -using Bitai.LDAPHelper.DTO; +using Bitai.LDAPHelper.DTO; using Bitai.LDAPHelper.Tests.Mocks.LdapAdapters; namespace Bitai.LDAPHelper.Tests @@ -35,7 +35,7 @@ public async Task CreateUserAccountForMsAD_ReturnsSuccess() { // Assert Assert.True(result.IsSuccessfulOperation); - Assert.Contains("user account created at", result.OperationMessage.ToLower()); + Assert.Contains("ms ad user account created at", result.OperationMessage.ToLower()); } [Fact] @@ -263,4 +263,4 @@ public async Task RemoveUserAccountForMsAD_AccountNotFound_ReturnsSuccess() { Assert.Contains("does not exist", result.OperationMessage.ToLower()); } } -} \ No newline at end of file +} diff --git a/tests/Bitai.LDAPHelper.Tests/Bitai.LDAPHelper.Tests.csproj b/tests/Bitai.LDAPHelper.Tests/Bitai.LDAPHelper.Tests.csproj index d36e0d3..0b9177b 100644 --- a/tests/Bitai.LDAPHelper.Tests/Bitai.LDAPHelper.Tests.csproj +++ b/tests/Bitai.LDAPHelper.Tests/Bitai.LDAPHelper.Tests.csproj @@ -1,22 +1,31 @@ - net8.0 + net10.0 enable enable false true - 8.6.0.0 - 8.6.0.0 + 10.0.0 + 10.0.0 + 10.0.0 + 5981b6a0-6b9e-439d-8324-a0ef8bfd0f11 - - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive +