Open Closed

External Provider login is able to register a user even if "self-register" setting is disabled #6843


User avatar
0
roberto.fiocchi created
  • ABP Framework version: v8.1.0-rc.2
  • UI Type: Blazor WASM
  • Database System: EF Core (SQL Server)
  • Tiered (for MVC) or Auth Server Separated (for Angular): no
  • Exception message and full stack trace: none
  • Steps to reproduce the issue:
  • Create a new Abp Blazor wasm project
  • Disable the "enable self registration" setting in the setting page:
  • Implement the code necessary for Azure AD login with external provider:
  • Log into the application using a Azure AD user that doesnt have an account on the application
  • Notice how the application still prompt you with the register option for the account:

If you press the "register" button it will create a new user, this behavior is not correct because it should only let you login if you already have a user in the application, otherwise it should stop you from registering because of the "self registration" setting.


11 Answer(s)
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    This is by design, He is registered as an external user.

  • User Avatar
    0
    roberto.fiocchi created

    Hi,

    If there is an option to prevent a new registration I expect that this will never happen and that the external provider will only be able to log in. How can I change the code to make my solution compliant?

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    You can try this:

    [ExposeServices(typeof(RegisterModel))]
    public class MyRegisterModel : RegisterModel
    {
        public MyRegisterModel(IAuthenticationSchemeProvider schemeProvider, IOptions<AbpAccountOptions> accountOptions, IAccountExternalProviderAppService accountExternalProviderAppService, ICurrentPrincipalAccessor currentPrincipalAccessor, IHttpClientFactory httpClientFactory) : base(schemeProvider, accountOptions, accountExternalProviderAppService, currentPrincipalAccessor, httpClientFactory)
        {
        }
    
        public override async Task<IActionResult> OnGetAsync()
        {
            ExternalProviders = await GetExternalProviders();
            if (!await CheckSelfRegistrationAsync())
            {
                if (IsExternalLoginOnly)
                {
                    return await OnPostExternalLogin(ExternalLoginScheme);
                }
    
                Alerts.Warning(L["SelfRegistrationDisabledMessage"]);
                return Page();
            }
            
            if (IsExternalLogin)
            {
                var externalLoginInfo = await SignInManager.GetExternalLoginInfoAsync();
                if (externalLoginInfo == null)
                {
                    Logger.LogWarning("External login info is not available");
                    return RedirectToPage("./Login");
                }
    
                
                var identity = externalLoginInfo.Principal.Identities.First();
                var emailClaim = identity.FindFirst(AbpClaimTypes.Email) ?? identity.FindFirst(ClaimTypes.Email);
                if (emailClaim == null)
                {
                    throw new AbpException("Could not find an email address for the user from the external login info!");
                }
    
                var userName = await UserManager.GetUserNameFromEmailAsync(emailClaim.Value);
                
                var user = await RegisterExternalUserAsync(externalLoginInfo,userName, emailClaim.Value);
                await SignInManager.SignInAsync(user, isPersistent: true, authenticationMethod: ExternalLoginAuthSchema);
    
                // Clear the dynamic claims cache.
                await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(user.Id, user.TenantId);
                return Redirect(ReturnUrl ?? "/"); 
                
            }
    
            Alerts.Warning(L["SelfRegistrationDisabledMessage"]);
            return Page();
        }
    }
    
  • User Avatar
    0
    roberto.fiocchi created

    Hi,

    I tried the code you suggested but it seems like it automatically registers the user which is not the behavior that i needed. I needed to block the user from self-registering no matter the origin (local or external provider). Digging through the code i might have found a solution:

    public override async Task<IActionResult> OnGetAsync()
    {
        ExternalProviders = await GetExternalProviders();
        if (!await CheckSelfRegistrationAsync())
        {
            //if (IsExternalLoginOnly)
            //{
            //    return await OnPostExternalLogin(ExternalLoginScheme);
            //}
    
            Alerts.Warning(L["SelfRegistrationDisabledMessage"]);
            return Page();
        }
    
        await TrySetEmailAsync();
    
        return Page();
    }
    
    protected override async Task<bool> CheckSelfRegistrationAsync()
    {
        EnableLocalRegister = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin) &&
                              await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled);
    
        //if (IsExternalLogin)
        //{
        //    return true;
        //}
    
        if (!EnableLocalRegister)
        {
            return false;
        }
    
        return true;
    }
    

    Is this a valid approach?

    Thanks

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    but it seems like it automatically registers the user which is not the behavior that i needed.

    Unfortunately, the system must have a user.

  • User Avatar
    0
    roberto.fiocchi created

    In fact the implemented workflow is that the admin registers a user with name.surname@mydomain.com and only then can he access the web portal. This seems to me to be the only solution to block access to unauthorized domain users. Or are there other options?

    Thanks

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    You can check the email of the external user and response unauthorized(401) if it's not allowed.

  • User Avatar
    0
    roberto.fiocchi created

    Hi,

    What method do you recommend doing this?

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer
    [ExposeServices(typeof(RegisterModel))]
    public class MyRegisterModel : RegisterModel
    {
        public MyRegisterModel(IAuthenticationSchemeProvider schemeProvider, IOptions<AbpAccountOptions> accountOptions, IAccountExternalProviderAppService accountExternalProviderAppService, ICurrentPrincipalAccessor currentPrincipalAccessor, IHttpClientFactory httpClientFactory) : base(schemeProvider, accountOptions, accountExternalProviderAppService, currentPrincipalAccessor, httpClientFactory)
        {
        }
    
        public override async Task<IActionResult> OnGetAsync()
        {
            .......
            if (IsExternalLogin)
            {
                ......
                var emailClaim = identity.FindFirst(AbpClaimTypes.Email) ?? identity.FindFirst(ClaimTypes.Email);
                if (emailClaim == null)
                {
                    throw new AbpException("Could not find an email address for the user from the external login info!");
                }
                
                var emailAddress = emailClaim.Value;
                
                // you can check the emailAddress here
     
                ......
                
            }
    
            ......
        }
    }
    
  • User Avatar
    0
    roberto.fiocchi created

    Ok, I will also try this solution and I will give you feedback.

    Thank you!

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    ok

Made with ❤️ on ABP v9.1.0-preview. Updated on November 01, 2024, 05:35