abpframework / abp

Open Source Web Application Framework for ASP.NET Core. Offers an opinionated architecture to build enterprise software solutions with best practices on top of the .NET and the ASP.NET Core platforms. Provides the fundamental infrastructure, production-ready startup templates, application modules, UI themes, tooling, guides and documentation.
https://abp.io
GNU Lesser General Public License v3.0
12.27k stars 3.32k forks source link

Azure users can switch to password-only login #19591

Closed ebicoglu closed 3 days ago

ebicoglu commented 2 weeks ago

this issue has been reported by a customer:

Azure users can switch to password-only login

If an Azure user sets their user password in the profile, login is possible via username & password (without OAuth/OIDC). This bypasses the log-in via the external provider (Azure Entra) and deactivates any second factor for 2FA.

Recommendation:

Using an implementation to force Azure users to always log in via OAuth/OIDC and not via password. In many apps, it is wanted that you can log in via an external provider or username & password. However, it would be good to be able to control this a little better via configuration. I have seen that the option "Authenticate with a local account" can be deactivated. But then the login page is completely deactivated. However, we have overwritten this, and we absolutely need it (we have additional information, links and the button for the Microsoft login there). Our current solution would be to remove the fields for username & password. Being able to do this via configuration would be great.

maliming commented 1 week ago

If an Azure user sets their user password in the profile, login is possible via username & password (without OAuth/OIDC). This bypasses the log-in via the external provider (Azure Entra) and deactivates any second factor for 2FA.

This doesn't seem to be related to the abp framework? Can the customer provide more information?

ebicoglu commented 1 week ago

We'll add the test scenarios here...

gizemmutukurt commented 1 week ago
  1. When I want to log in with a Google profile and the 'Authenticate with a local account' selection is true; The Abp login page opens and I can log in either with Google or with the registered username and password.

(The file has been zipped because the video is large) Login_1713967260806.zip

  1. When I want to log in with a Google profile and the 'Authenticate with a local account' selection is false; When I click on the login button, it takes me directly to the Google login screen.

Login2_1713967329367.webm

3.If more than one External provider is added and the 'Authenticate with a local account' selection is false; It redirects to Abp login, user name and password is not visible and provider selections are displayed.

Login3_1713967397953.webm

ageiter commented 1 week ago

Hi, I am the customer who originally made this issue.

The situation is that the main users of the application are only allowed to log in via the external provider (Azure). However, a local login should still be possible for the host admin (in case the external provider cannot be reached).

However, we have now defined that we deactivate the local login and activate it with a DB script in an emergency (this situation, where Azure Entra is not accessible, should occur very rarely).

The problem now is that the login page is not displayed if we only have one external provider and the local login is deactivated. However, we have to display the login page in any case, as we have placed other links there (e.g. apply for an account in the IAM).

maliming commented 1 week ago

hi @ageiter

Your situation is special. So you can override the CheckLocalLoginAsync method of the LoginModel page.

Or you can use a special get parameter to show the login form.

https://localhost/Account/Login?enableLocalLogin=true


public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1;

public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null;

protected virtual async Task<IActionResult> CheckLocalLoginAsync()
{
    ExternalProviders = await GetExternalProviders();
    EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin);

    if (!EnableLocalLogin && IsExternalLoginOnly && ExternalLoginScheme != null)
    {
        return await OnPostExternalLogin(ExternalLoginScheme);
    }

    if (!EnableLocalLogin)
    {
        Alerts.Warning(L["LocalLoginIsNotEnabled"]);
        return Page();
    }

    return null;
}
ageiter commented 3 days ago

Thank you, that works by overwriting CheckLocalLoginAsync.