aspnetboilerplate – Add tenant name to the url after authentication in asp.net zero – Code Utility

I want to redirect the URL after authentication in multi-tenant application.

When user enters credentials on login page(URL: domain_name.com) and after successful authentication, browser URL must changed to {tenancy_name}.domain_name.com

I got tenancy name using email address and password. Now, I want to put that tenancy name into browser URL to get it identified for user.

This is a case when user forgot to put tenancy name in URL means user enters URL like: domain_name.com

Then after successful authentication, tenancy name must be added to URL like:
{tenancy_name}.domain_name.com

And must redirect to the dashboard page.

Following is my Login post method:

        HttpPost
        UnitOfWork
        public virtual async Task<ActionResult> Login(LoginViewModel loginModel, int paymentFlag, string returnUrl = "", string returnUrlHash = "")
        {
            try
            {
                var tenant = await _tenantManager.FindByTenancyNameAsync(loginModel.TenancyName);
                if (tenant.IsActive == true)
                {
                    if (tenant != null)
                    {
                        var payments = await _paymentRepository.GetAll().Where(p => p.TenantId == tenant.Id).FirstOrDefaultAsync();

                        if (paymentFlag == 0)
                        {
                            if (payments == null)
                            {
                                return RedirectToAction("Payment", loginModel);
                            }
                        }

                    }

                    var loginResult = await GetLoginResultAsync(loginModel.UsernameOrEmailAddress, loginModel.Password, loginModel.TenancyName);

                    var tenantId = loginResult.Tenant == null ? (int?)null : loginResult.Tenant.Id;

                    using (UnitOfWorkManager.Current.SetTenantId(tenantId))
                    {
                        if (loginResult.User.ShouldChangePasswordOnNextLogin)
                        {
                            loginResult.User.SetNewPasswordResetCode();

                            return RedirectToAction("ResetPassword", new
                            {
                                TenantId = SimpleStringCipher.Instance.Encrypt(tenantId == null ? null : tenantId.ToString()),
                                UserId = SimpleStringCipher.Instance.Encrypt(loginResult.User.Id.ToString()),
                                ResetCode = loginResult.User.PasswordResetCode
                            });
                        }

                        var signInResult = await _signInManager.SignInOrTwoFactorAsync(loginResult, loginModel.RememberMe);
                        if (signInResult == SignInStatus.RequiresVerification)
                        {


                            return RedirectToAction("SendSecurityCode", new
                            {
                                returnUrl = returnUrl + (returnUrlHash ?? ""),
                                rememberMe = loginModel.RememberMe
                            });
                        }

                        Debug.Assert(signInResult == SignInStatus.Success);

                        await UnitOfWorkManager.Current.SaveChangesAsync();

                        if (string.IsNullOrWhiteSpace(returnUrl))
                        {
                            returnUrl = GetAppHomeUrl();
                        }

                        if (!string.IsNullOrWhiteSpace(returnUrlHash))
                        {
                            returnUrl = returnUrl + returnUrlHash;
                        }


                    }
                }
                else
                {
                    throw new UserFriendlyException(L("UserEmailIsNotConfirmedAndCanNotLogin"));
                }
            }
            catch (UserFriendlyException ex)
            {
                return RedirectToAction("Login", new
                {
                    errorMessage = ex.Message
                });
            }
            return Json(new AjaxResponse { TargetUrl = returnUrl });                
        }

,

I found a simple solution. Update app-initializer.ts as follows:

First, add method

private replaceTenantPlaceholder(baseUrl: string, defaultSubDomain: string): string {

    const tenancyNamePlaceHolder = '{TENANCY_NAME}';
    baseUrl = baseUrl.replace(tenancyNamePlaceHolder + '.', tenancyNamePlaceHolder);
    
    var subDomain = window.location.hostname.split(".")0;
    subDomain = subDomain.replace(`$:{window.location.port}`, "");
    
    switch (window.location.hostname.split(".").length) {
        case 1:
        case 2:
            //No sub-domain on current url
            subDomain = defaultSubDomain;
            if (subDomain.length > 0) subDomain += ".";
            break;

        case 3:
            //Use the current url's sub-domain
            subDomain += ".";

        default:
    }
    
    return baseUrl.replace(tenancyNamePlaceHolder, subDomain);
}

Then update method getApplicationConfig:

AppConsts.appBaseUrl = this.replaceTenantPlaceholder(response.appBaseUrl, "www");
AppConsts.remoteServiceBaseUrl = this.replaceTenantPlaceholder(response.remoteServiceBaseUrl, "");

No other modifications needed for this part of the multi-tenancy. Make sure you update your Configuration.Modules.AbpWebCommon().MultiTenancy.DomainFormat in your CoreModule and define your CorsOrigins in appsettings.json

My client application requires “www” in the domain, so that is why I have the defaultSubDomain parameter. You can omit that if not needed.

Leave a Comment