Open Closed

How to restrict tenant access by domain in a multi-tenant Angular app? #9661


User avatar
0
rexhxiao created

Can a multi-tenant Angular app support logging in to the same auth server from different domains, while preventing switching to other tenants? Below is my Angular dynamic-env.json configuration.

{ "production": true, "application": { "baseUrl": "https://{0}.koimpact.tw", "name": "Sroi" }, "oAuthConfig": { "issuer": "https://auth-imm.koimpact.tw/", "redirectUri": "https://{0}.koimpact.tw", "clientId": "Sroi_App", "responseType": "code", "scope": "offline_access Sroi", "requireHttps": true }, "apis": { "default": { "url": "https://api-imm.koimpact.tw", "rootNamespace": "Aws.Sroi" }, "AbpAccountPublic": { "url": "https://api-imm.koimpact.tw", "rootNamespace": "AbpAccountPublic" } } }


24 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent

    To restrict tenant access by domain in a multi-tenant Angular app using ABP Framework, and to prevent users from switching to other tenants, you should use the domain/subdomain tenant resolver both on the backend and frontend. This ensures that each tenant is only accessible from its assigned domain, and tenant switching is disabled.

    Solution Steps:

    1. Frontend (Angular) Configuration:
      • Set the baseUrl in your environment configuration to use the {0} placeholder for the tenant name:

    application: { baseUrl: "https://{0}.koimpact.tw", name: "Sroi" }

       - With this setup, when the app runs on `https://imm.koimpact.tw`, the tenant name will be resolved as `imm`. The Angular app will send the `__tenant` header automatically based on the subdomain.
    
       - When you use the `{0}` placeholder in `baseUrl`, the tenant switching component (e.g., on the login page) will be hidden, so users cannot switch tenants from the UI.
    
    2. **Backend Configuration:**
       - In your backend (e.g., in `YourProjectNameHttpApiHostModule`), configure the domain tenant resolver:
         ```csharp
    Configure<AbpTenantResolveOptions>(options =>
         {
             options.AddDomainTenantResolver("{0}.koimpact.tw");
         });
    
    • This ensures that the backend only resolves the tenant from the subdomain and does not allow switching tenants via headers or query strings.
    1. Identity Server / Auth Server:

      • Make sure your IdentityServer or OpenIddict client configuration allows redirect URIs for each tenant domain (e.g., https://imm.koimpact.tw).
      • Do not use wildcards like https://*.koimpact.tw in CORS or redirect URIs; instead, explicitly list each allowed tenant domain.
    2. Preventing Tenant Switching:

      • With the above configuration, the Angular app will not show the tenant switcher, and the backend will only resolve tenants by domain. Users cannot switch tenants by manipulating headers or query strings.

    Summary:

    • Use {0} in baseUrl for tenant isolation.
    • Configure backend to resolve tenants only by domain.
    • List each tenant domain explicitly in your auth server's allowed origins and redirect URIs.
    • Tenant switching is automatically disabled in the UI with this setup.

    Sources:


    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • User Avatar
    0
    rexhxiao created

    Can you help me check where my system has misconfigured settings that allow public access?

    https://imm.koimpact.tw/

  • User Avatar
    0
    rexhxiao created

    AuthServer

    `public override void PreConfigureServices(ServiceConfigurationContext context) { var hostingEnvironment = context.Services.GetHostingEnvironment(); var configuration = context.Services.GetConfiguration();

        PreConfigure<OpenIddictBuilder>(builder =>
        {
            builder.AddValidation(options =>
            {
                options.AddAudiences("Sroi");
                options.UseLocalServer();
                options.UseAspNetCore();
            });
        });
    
        if (!hostingEnvironment.IsDevelopment())
        {
            PreConfigure<AbpOpenIddictAspNetCoreOptions>(options =>
            {
                options.AddDevelopmentEncryptionAndSigningCertificate = false;
            });
    
            PreConfigure<OpenIddictServerBuilder>(serverBuilder =>
            {
                serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", configuration["AuthServer:CertificatePassPhrase"]!);
                serverBuilder.SetIssuer(new Uri(configuration["AuthServer:Authority"]!));
            });
    
            PreConfigure<AbpOpenIddictWildcardDomainOptions>(options =>
            {
                options.EnableWildcardDomainSupport = true;
                
                var domainsFormat = configuration.GetValue<string>("App:DomainsFormat");
    
                if (!string.IsNullOrWhiteSpace(domainsFormat))
                {
                    foreach (var domainFormat in domainsFormat.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
                    {
                        options.WildcardDomainsFormat.Add(domainFormat);
                    }
                }
            });
        }
    }`
    
  • User Avatar
    0
    rexhxiao created

    docker-compose.yml

    sroi-auth: image: sroi-authserver:0.0.10 environment: - App__CorsOrigins=https://*.koimpact.tw,https://sroi-admin.awesome-tech.link - App__SelfUrl=https://auth-imm.koimpact.tw - App__RedirectAllowedUrls=https://imm.koimpact.tw,https://sroi-admin.awesome-tech.link - App__domainsFormat=https://{0}.koimpact.tw - AuthServer__Authority=https://auth-imm.koimpact.tw

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    What is the current behavior of your website during the login process?

    Thanks.

  • User Avatar
    0
    rexhxiao created

    Hello, first of all, when attempting to log in to the website, it successfully reaches the authserver but shows a tenant switching option.

    However, in the Angular app, I can see that it retrieves the IMM tenant based on the base application URL.

    Then, in the authserver, whether I try to log in with the host account credentials or the IMM (tenant) account credentials, the login fails. The Angular app keeps redirecting back and forth to the authserver in a loop.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    whether I try to log in with the host account credentials or the IMM (tenant) account credentials, the login fails. The Angular app keeps redirecting back and forth to the authserver in a loop.

    Please share the Debug logs.txt of the AuthServer. https://abp.io/support/questions/8622/How-to-enable-Debug-logs-for-troubleshoot-problems

    Thanks.

  • User Avatar
    0
    rexhxiao created

    AuthServer logs.txt https://drive.google.com/file/d/1yDKkGTFL9TuIfHwxEnNd__OmM1Abv2wH/view?usp=sharing

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    There is no error in the logs.

    Can you share a username and password?

    I will test it online.

    Thanks.

  • User Avatar
    0
    rexhxiao created

    host admin / 1q2w3E*

    imm admin / 1q2w3E*

    https://imm.koimpact.tw/

  • User Avatar
    0
    rexhxiao created

    Host Admin Site: We plan to use http://sroi-admin.awesome-tech.link/ as the host admin site.

    Auth Server: Configured as https://imm-auth.koimpact.tw/ API Endpoint: Configured as https://imm-api.koimpact.tw/

    First Tenant: The first tenant is set up as https://imm.koimpact.tw/. In the future, we expect to add other tenants, such as https://other-tenant.koimpact.tw/.

    Question: Can this setup work as intended?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Auth Server: Configured as https://imm-auth.koimpact.tw/ API Endpoint: Configured as https://imm-api.koimpact.tw/

    Is the imm the tenant's name?

    If you have a new tenant test

    Auth Server: Configured as https://test-auth.koimpact.tw/ API Endpoint: Configured as https://test-api.koimpact.tw/

  • User Avatar
    0
    rexhxiao created

    So, we cannot have multiple tenants pointing to the same auth server (e.g., auth.koimpact.tw)? Instead, does each tenant require its own dedicated configuration, like:

    https://{0}-auth.koimpact.tw/

    https://{0}-api.koimpact.tw/

    And is this configured via:

    csharp Configure<AbpTenantResolveOptions>(options =>
    {
    options.AddDomainTenantResolver(configuration["TenantDomain"]);
    });
    Is that correct?

  • User Avatar
    0
    rexhxiao created

    [maliming] said: hi

    Auth Server: Configured as https://imm-auth.koimpact.tw/ API Endpoint: Configured as https://imm-api.koimpact.tw/

    Is the imm the tenant's name?

    If you have a new tenant test

    Auth Server: Configured as https://test-auth.koimpact.tw/ API Endpoint: Configured as https://test-api.koimpact.tw/

    Is the imm the tenant's name? Yes.

  • User Avatar
    0
    rexhxiao created

    Option 1 (Preferred Approach) For all tenants:

    Auth Server: https://auth.koimpact.tw/

    API: https://api.koimpact.tw/

    For each tenant's Angular app:

    https://{0}-app.koimpact.tw/

    Option 2 For each tenant:

    Auth Server: https://{0}-auth.koimpact.tw/

    API: https://{0}-api.koimpact.tw/

    Angular App: https://{0}-app.koimpact.tw/

    Question: Are both of these options feasible, or is only Option 2 possible?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    You can use same authserver and api domain for different domains angular apps.

    The current error is from angular.

    Can you make your angular home component doesn’t require authorization?

    Which means I have to click login button in angular website then redirect to authserver.

    Thanks.

  • User Avatar
    0
    rexhxiao created

    [maliming] said: hi

    You can use same authserver and api domain for different domains angular apps.

    The current error is from angular.

    Can you make your angular home component doesn’t require authorization?

    Which means I have to click login button in angular website then redirect to authserver.

    Thanks.

    It will have to wait until I release a new version. Thank you.

  • User Avatar
    0
    rexhxiao created

    You're right. I removed the following code, and now the login works fine—manually going to the dashboard works as expected. https://imm.koimpact.tw/dashboard

    However, for my tenant Angular app, how should it reach the auth server with tenant identification? Currently, it can switch tenants, which is not the result we want.

  • User Avatar
    0
    rexhxiao created
    import { AuthService } from '@abp/ng.core';
    import { Component, inject } from '@angular/core';
    import { Router } from '@angular/router';
    
    @Component({
      standalone: false,
      selector: 'app-home',
      templateUrl: './home.component.html',
      styleUrls: ['./home.component.scss'],
    })
    export class HomeComponent {
      private router = inject(Router);
      get hasLoggedIn(): boolean {
        return this.authService.isAuthenticated;
      }
      constructor(private authService: AuthService) {
        // if (this.hasLoggedIn) {
        //   this.goDashboard();
        // }
        // else {
        //   this.login();
        // }
      }
    
      login() {
        this.authService.navigateToLogin();
      }
    
      goDashboard() {
        this.router.navigate([`/dashboard`]);
      }
    }
    

    Why can't we do it this way?

  • User Avatar
    0
    rexhxiao created

    [maliming] said: hi

    You can use same authserver and api domain for different domains angular apps.

    The current error is from angular.

    Can you make your angular home component doesn’t require authorization?

    Which means I have to click login button in angular website then redirect to authserver.

    Thanks.

    How can I configure it so that the tenant app does not display the tenant switching feature when redirecting to the authserver?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    The HomeComponent will also use code to get an access token. We will enhance it in the next version. Please follow https://github.com/abpframework/abp/issues/23286


    this.authService.navigateToLogin();

    You can pass the __tenant to the query string when doing the code flow.

    I will ask Angular how to do this.

    Thanks.

  • User Avatar
    0
    rexhxiao created

    Thanks.

    Clients have reported that the SessionStateService frequently fails to retrieve the correct tenant information in new web environments or incognito mode. Our tests confirm this issue. Has there been any solution to this problem yet?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    You're welcome.

  • User Avatar
    0
    sumeyye.kurtulus created
    Support Team Angular Expert

    Hello,

    As my colleague has mentioned, you can pass the __tenant parameter for the authService.navigateToLogin() function.
    https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts#L78-L86

    Here is how you could achieve that:

    import { SessionStateService } from '@abp/ng.core';
    // ...
    export class HomeComponent {
    	// ...
    	sessionStateService = inject(SessionStateService);
    
    	login(){
    		const tenantId = this.sessionStateService.getTenant().id || null;
    		if(tenantId){
    			this.authService.navigateToLogin({
    				__tenant: `${tenantId}`
    			});	
    		} else {
    			this.authService.navigateToLogin();
    		}
    	}
    }
    
    
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.0.0-preview. Updated on September 04, 2025, 08:36