Discussion on the module zero. Module zero implements authorization, user management, role management, setting management and multi-tenancy for applications.
User avatar
By VarPippo
#18268 I followed the instructions available here https://www.aspnetboilerplate.com/Pages ... entication to configure the LDAP authentication and it's working as expected when invoked via:

Code: Select all private async Task<AbpLoginResult<Tenant, User>> GetLoginResultAsync(string usernameOrEmailAddress, string password, string tenancyName)
        {
            var loginResult = await _logInManager.LoginAsync(usernameOrEmailAddress, password, tenancyName);

            switch (loginResult.Result)
            {
                case AbpLoginResultType.Success:
                    return loginResult;
                default:
                    throw CreateExceptionForFailedLoginAttempt(loginResult.Result, usernameOrEmailAddress, tenancyName);
            }
        }


TryAuthenticateAsync is invoked as expected and it works smoothly, but I'd need to use 2 distinct authentication methods:

    * LdapAuthenticationSource --> TryAuthenticateAsync if userNameOrEmailAddress is an e-mail address OR if it's in the format domain\username
    * The local data (e.g. accounts available in dbo.AbpUsers) otherwise

Is there any way to combine the default authentication mechanism (=without LDAP/External source) with LDAP, based on some conditions?

I mean, is there any way to "chain" different authentication approaches as fallbacks ?
As an alternative, is it possible to invoke the "local" authentication from inside TryAuthenticateAsync in case usernameOrEmailAddress is not a valid username/e-mail?
By ismcagdas
#18363 Hi,

This is not possible by default but you have two options.

1. Define your own loginManager whic is derived from AbpLoginManager and ovverride LoginAsync method to do this.
2. Define an external auto source for example MixedExternalAuthSource (you can find a better name :)), and call Ldap and Local auth sources conditionally in it.
https://aspnetboilerplate.com/Pages/Doc ... entication

Thanks.
User avatar
By VarPippo
#18382 Hi!

Thank you for your feedback :idea:

I managed to implement it as follows:

1) In the Web project GetLoginResultAsync invokes:
Code: Select allvar loginResult = await _logInManager.LoginAsync(usernameOrEmailAddress, password, tenancyName, false);


2) TryAuthenticateAsync takes this actions:
    * It tries to understand if userNameOrEmailAddress is a valid&known e-mail or domain\username
    * Invokes ValidateCredentials only if userNameOrEmailAddress exists in AD
    * In all other cases it returns false

3) var loggedInFromExternalSource = await TryLoginFromExternalAuthenticationSources(userNameOrEmailAddress, plainPassword, tenant);

can be either true (the authentication through LDAP went fine) or false (userNameOrEmailAddress is invalid / not existing). If it's false the default LoginAsyncInternal method is smart enough to attempt an "internal" authentication:

Code: Select all return await CreateLoginResultAsync(user, tenant);


I hope that helps someone ;)

PS. I implemented CreateUserAsync to store in dbo.AbpUsers information like Username/Mail/First name/Last name obtained from AD and it works perfectly, but I'm not sure if it makes sense to have a UpdateUserAsync like this in the class derived from LdapAuthenticationSource:

Code: Select all public async override Task UpdateUserAsync(User user, Tenant tenant)
        {
            await Task.Run(() => { }); // Nothing to do for the time being. LastLoginTime and other fields are updated automatically?
        }


We don't want to update users created with AuthenticationSource = LDAP
User avatar
By VarPippo
#18383 Using the approach described above we allow the users to login using one of the following options:

LDAP:
- Valid AD e-mail address and AD password
- Valid AD domain\username and AD password
- Valid AD username and AD password

if the authentication fails, a last attempt is made:

LOCAL DATABASE:
- Valid combination of username / password ( Configuration.MultiTenancy.IsEnabled is commented out, so hopefully we disabled multi-tenancy :) )

We really appreciate the design behind ASP.NET Boilerplate! 8-)
By ismcagdas
#18443 Hi @VarPippo,

Thank you very much for sharing your solution and detailed explanation :).
The reason for UpdateUserAsync is, information of user on Ldap might change.

User can move to another group, can get married and have a different surname :) etc..., but you don't have to use it.

Thanks again.
User avatar
By VarPippo
#18457 Thank you!

We're storing some basic details in AbpUsers with CreateUserAsync , but essentially we need only a standardized format of the username: regardless to what is used for the first login (username, domain\username, e-mail), we convert the username to the AD username. Some additional details like first name and last name are retrieved and stored, but we're not using them in any way.

So, as long as, having an "empty" UpdateUserAsync method does not create any issues to ASP.NET Boilerplate inner mechanisms, I'm fine with that!
:D