Open Closed

ImpersonateTenant not work with subdomain tenant resolver #6813


User avatar
0
hitaspdotnet created
  • ABP Framework version: v8.1.0-rc.1
  • UI Type: MVC
  • Database System: MongoDB
  • Tiered (for MVC) or Auth Server Separated (for Angular): yes/ ABP Studio Microservice
  • Exception message and full stack trace: N/A
  • Steps to reproduce the issue: N/A

Hi, I added subdomain tenant resolver to my abp application. everything works except "login as this tenant" and user menus "Security Log" & "My Account" has invalid url (actually I fixed it with {0} replacer). When I trying to impersonate tenant from host dashboard it's just redirect to the host home page. I think this is related to the tenant resolver. I expected it to impersonate the tenant on the host domain. Do we have a list of resolvers? Can we fix this by resolvers ordering?


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

    Hi,

    How do you configure the subdomain tenant resolver?

    Could you share your steps?

  • User Avatar
    0
    hitaspdotnet created

    Hi,

    How do you configure the subdomain tenant resolver?

    Could you share your steps?

    in web, web.public & authserver I added:

    Configure<AbpTenantResolveOptions>(options =>
    {
        options.AddDomainTenantResolver(configuration["TenantDomain"]);
    });
    

    also this config in their appSettings:

    "TenantDomain": "https://{0}.app.domain.com"
    ...
    "TenantDomain": "https://{0}.pub.domain.com"
    ...
    "TenantDomain": "https://{0}.auth.domain.com"
    

    in authserver module:

    PreConfigure<AbpOpenIddictWildcardDomainOptions>(options =>
    {
        options.EnableWildcardDomainSupport = true;
        options.WildcardDomainsFormat.Add(configuration["WildCardDomains:AuthServer"]);
        options.WildcardDomainsFormat.Add(configuration["WildCardDomains:Web"]);
        options.WildcardDomainsFormat.Add(configuration["WildCardDomains:PublicWeb"]);
    });
    

    and authserver's appSettings:

    "WildCardDomains": {
        "AuthServer": "https://{0}.auth.domain.com",
        "Web": "https://{0}.app.domain.com",
        "PublicWeb": "https://{0}.pub.domain.com"
    }
    

    then in web & web.public :

    if (Convert.ToBoolean(configuration["AuthServer:IsOnK8s"]))
    {
        context.Services.Configure<OpenIdConnectOptions>(
            "oidc", options =>
            {
                options.MetadataAddress = configuration["AuthServer:MetaAddress"]!.EnsureEndsWith('/') +
                                          ".well-known/openid-configuration";
    
                var previousOnRedirectToIdentityProvider = options.Events.OnRedirectToIdentityProvider;
                options.Events.OnRedirectToIdentityProvider = async ctx =>
                {
                    ctx.ProtocolMessage.IssuerAddress = configuration["AuthServer:Authority"]!.EnsureEndsWith('/') + "connect/authorize";
    
                    var currentTenant = ctx.HttpContext.RequestServices.GetRequiredService<ICurrentTenant>();
                    var tenantDomain = configuration["TenantDomain"];
    
                    if (currentTenant.IsAvailable && !string.IsNullOrEmpty(tenantDomain))
                    {
                        ctx.ProtocolMessage.IssuerAddress =
                            ctx.ProtocolMessage.IssuerAddress.Replace("{0}", $"{currentTenant.Name}");
                    }
                    else
                    {
                        ctx.ProtocolMessage.IssuerAddress =
                            ctx.ProtocolMessage.IssuerAddress.Replace("{0}.", string.Empty);
                    }
    
                    if (previousOnRedirectToIdentityProvider != null)
                    {
                        await previousOnRedirectToIdentityProvider(ctx);
                    }
                };
    
                var previousOnRedirectToIdentityProviderForSignOut =
                    options.Events.OnRedirectToIdentityProviderForSignOut;
                options.Events.OnRedirectToIdentityProviderForSignOut = async ctx =>
                {
                    // Intercept the redirection for signout so the browser navigates to the right URL in your host
                    ctx.ProtocolMessage.IssuerAddress = configuration["AuthServer:Authority"]!.EnsureEndsWith('/') +
                                                        "connect/logout";
    
                    var currentTenant = ctx.HttpContext.RequestServices.GetRequiredService<ICurrentTenant>();
                    var tenantDomain = configuration["TenantDomain"];
                    if (currentTenant.IsAvailable &&
                        !string.IsNullOrEmpty(tenantDomain))
                    {
                        ctx.ProtocolMessage.IssuerAddress =
                            ctx.ProtocolMessage.IssuerAddress.Replace("{0}", $"{currentTenant.Name}");
                    }
                    else
                    {
                        ctx.ProtocolMessage.IssuerAddress =
                            ctx.ProtocolMessage.IssuerAddress.Replace("{0}.", string.Empty);
                    }
    
                    if (previousOnRedirectToIdentityProviderForSignOut != null)
                    {
                        await previousOnRedirectToIdentityProviderForSignOut(ctx);
                    }
                };
            }
        );
    }
    

    and the userMenu in web & web.public

    var authServerUrl = _configuration["AuthServer:Authority"] ?? "~";
    var returnUrl = _configuration["App:SelfUrl"] ?? "";
    
    var currentTenant = context.ServiceProvider.GetRequiredService<ICurrentTenant>();
    var tenantDomain = _configuration["TenantDomain"];
    
    if (currentTenant.IsAvailable && !string.IsNullOrEmpty(tenantDomain))
    {
        authServerUrl = authServerUrl.Replace("{0}", $"{currentTenant.Name}");
        returnUrl = tenantDomain.Replace("{0}", $"{currentTenant.Name}");
    }
    else
    {
        authServerUrl = authServerUrl.Replace("{0}.", string.Empty);
    }
    

    I kept gateways and services as before except openIddict data seeder.

  • User Avatar
    0
    hitaspdotnet created

    is it possible to impersonate tenant on the host domain? If yes, please guide me!

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    There should be work. because the tenant is first determined from the current user and not the domain

    And it works for me

    Configure<AbpTenantResolveOptions>(options =>
    {
        options.AddDomainTenantResolver("{0}.localhost");
    });
    

  • User Avatar
    0
    hitaspdotnet created

    Do I need to config AuthServer:Authority in authServer too? After clicking on Login I see redirect to auth.domain.com which is host's issuer and then redirected to host home page. the url after click on login:

    https://auth.tonner.io/connect/authorize?client_id=Web&redirect_uri=https%3A%2F%2Fapp.tonner.io%2Fsignin-oidc&response_type=code%20id_token&scope=<scopes>&response_mode=form_post&nonce=<nonce>&access_token=<token>&tenantid=bec78466-c1c3-d8dc-beb3-3a112a214a25&tenantusername=admin&returnurl=https%3A%2F%2Fapp.tonner.io%2FSaas%2FHost%2FTenants&state=<state>&x-client-SKU=ID_NET8_0&x-client-ver=7.0.3.0
    
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    Will this can help you?

    https://github.com/abpframework/abp-samples/blob/master/DomainTenantResolver/MVC-TIERED/src/Acme.BookStore.Web/BookStoreWebModule.cs#L162-L176

  • User Avatar
    0
    hitaspdotnet created

    NO, I shared my code as you asked, and already added this.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    Can you try to remove the if (Convert.ToBoolean(configuration["AuthServer:IsOnK8s"])) code?

    Then you can test it locally to see if it works

  • User Avatar
    0
    hitaspdotnet created

    Hi, seems we have a PR related to this issue, Enable Login with this tenant for templates contains microservice-template label. please guide me using that PR if possible.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    The PR is basically the same as your code.

    Did you remove the if (Convert.ToBoolean(configuration["AuthServer:IsOnK8s"])) code?

  • User Avatar
    0
    hitaspdotnet created

    hi

    The PR is basically the same as your code.

    Did you remove the if (Convert.ToBoolean(configuration["AuthServer:IsOnK8s"])) code?

    now I see an error, my application is running on k8s, so the value is always true. I'm not sure why it made effect. however, how I can solve this error?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Please remember to configure the ImpersonationTenantPermission and ImpersonationUserPermission permissions

    See https://docs.abp.io/en/commercial/latest/modules/account/impersonation

Made with ❤️ on ABP v9.1.0-preview. Updated on December 12, 2024, 07:15