Open Closed

DomainTenantResolver for HttpApi.Host project in Tiered architecture #3413


User avatar
1
sh_erfan created

Hi Trying to implement DomanTenantResolver sample in my own project, everything is fine, except I cant use swagger in *HttpiApi.Host. Redirection from Identity back to api does not work. Neither with tenant available nor without tenant(host). I also tried to add OnChallenge event to JwtBearerOptions during configuration, but no success. I have no idea how to implement this. P.S: In your sample resolver, I cant event authorize with "web.getap.com:1234/swagger". In other words, api is out of reach.

Any help would be appreciated

  • ABP Framework version: 5.2.1
  • UI type: MVC
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): yes

10 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    How can I reproduce the problem via DomanTenantResolver sample?

  • User Avatar
    0
    sh_erfan created

    Hi there

    First simple scenario:

    • Head to DomainTenantResolver/MVC-TIERED
    • Add BookStore_Swagger client to appsettings.json in DbMigrator:
    "IdentityServer": {
        "Clients": {
          "BookStore_Web": {
            "ClientId": "BookStore_Web",
            "ClientSecret": "1q2w3e*",
            "RootUrl": "https://{0}.web.getabp.net:44303"
          },
          "BookStore_Swagger": {
            "ClientId": "BookStore_Swagger",
            "ClientSecret": "1q2w3e*",
            "RootUrl": "https://{0}.api.getabp.net:44302"
          }
        }
    
    • Add BookStore_Swagger client to IdentityDataSeedContributor.cs
    //Web Client
    var webClientId = configurationSection["BookStore_Web:ClientId"];
    if (!webClientId.IsNullOrWhiteSpace())
    {
    	var webClientRootUrl = configurationSection["BookStore_Web:RootUrl"].EnsureEndsWith('/');
    
    	/* BookStore_Web client is only needed if you created a tiered
    	 * solution. Otherwise, you can delete this client. */
    
    	await CreateClientAsync(
    		name: webClientId,
    		scopes: commonScopes,
    		grantTypes: new[] { "hybrid" },
    		secret: (configurationSection["BookStore_Web:ClientSecret"] ?? "1q2w3e*").Sha256(),
    		redirectUri: $"{webClientRootUrl}signin-oidc",
    		postLogoutRedirectUri: $"{webClientRootUrl}signout-callback-oidc",
    		frontChannelLogoutUri: $"{webClientRootUrl}Account/FrontChannelLogout",
    		corsOrigins: new[] { webClientRootUrl.RemovePostFix("/") }
    	);
    }
    
    // Swagger Client
    var swaggerClientId = configurationSection["BookStore_Swagger:ClientId"];
    if (!swaggerClientId.IsNullOrWhiteSpace())
    {
    	var swaggerRootUrl = configurationSection["BookStore_Swagger:RootUrl"].TrimEnd('/');
    
    	await CreateClientAsync(
    		name: swaggerClientId,
    		scopes: commonScopes,
    		grantTypes: new[] { "authorization_code" },
    		secret: (configurationSection["Recruitans_Swagger:ClientSecret"] ?? "1q2w3e*").Sha256(),
    		requireClientSecret: false,
    		redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html",
    		corsOrigins: new[] { swaggerRootUrl.RemovePostFix("/") }
    	);
    }
    
    • Run DbMigrator
    • Run multiple projects (ids, web,api)
    • Open swagger https://api.getabp.net:44302/swagger/index.html and try to authorize using host admin user. it fails on redirection.

    This is the initial scenario that I cant use swagger api.

  • User Avatar
    1
    maliming created
    Support Team Fullstack Developer

    hi src/Acme.BookStore.IdentityServer/appsettings.json

    Add https://api.getabp.net:44302 to CorsOrigins of IdentityServer project.

    "CorsOrigins": "https://*.api.getabp.net,https://*.web.getabp.net,https://api.getabp.net:44302"

    I will update the sample.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    https://github.com/abpframework/abp-samples/commit/4daebdd8a3b32b7fb47ac05e2ff69b834766e89b

  • User Avatar
    0
    sh_erfan created

    Actually this worked for me "https://*.api.getabp.net,https://*.web.getabp.net,https://api.getabp.net:44302" This is solution for host user authorization.

    Now, the second part. How should we handle https://tenant1.api.getabp.net:44302/swagger/index.html for tenant1?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    How should we handle https://tenant1.api.getabp.net:44302/swagger/index.html for tenant1?

    What do you mean?

  • User Avatar
    0
    sh_erfan created

    I want to implement resolver for web api project:

    Configure<AbpTenantResolveOptions>(options =>
    {
        options.AddDomainTenantResolver("{0}.api.getabp.net:44302");
    });
    

    Then, I want to go to https://tenant1.api.getabp.net:44302/swagger/index.html When authorizing, I want to be automatically be directed to https://tenant.ids.getabp.net:44301 After that, redirect back to https://tenant1.api.getabp.net:44302/swagger/index.html Now, my swagger client is authorized and the active tenant is tenant1 Hence, current tenant id will tenant1 id. Just like web project.

    Hope you understand

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    I don't know if swagger supports custom authorize urls, I'll check.

  • User Avatar
    1
    maliming created
    Support Team Fullstack Developer

    Can you try this?

    
    services.AddAbpSwaggerGenWithOAuth(
    services.AddTransient<SwaggerGenerator>();
    services.Replace(ServiceDescriptor.Transient<ISwaggerProvider, MySwaggerGenerator>());
    
    using System;
    using Microsoft.OpenApi.Models;
    using Swashbuckle.AspNetCore.Swagger;
    using Swashbuckle.AspNetCore.SwaggerGen;
    using Volo.Abp.MultiTenancy;
    
    namespace MyCompanyName.MyProjectName.Web;
    
    public class MySwaggerGenerator : ISwaggerProvider
    {
        private readonly SwaggerGenerator _innerSwaggerGenerator;
        private readonly SwaggerGeneratorOptions _options;
        private readonly ICurrentTenant _currentTenant;
    
        public MySwaggerGenerator(SwaggerGenerator innerSwaggerGenerator, SwaggerGeneratorOptions options, ICurrentTenant currentTenant)
        {
            _innerSwaggerGenerator = innerSwaggerGenerator;
            _options = options;
            _currentTenant = currentTenant;
        }
    
        public OpenApiDocument GetSwagger(string documentName, string host = null, string basePath = null)
        {
            foreach (var securityScheme in _options.SecuritySchemes)
            {
                if (securityScheme.Value.Flows.AuthorizationCode != null && _currentTenant.IsAvailable)
                {
                    securityScheme.Value.Flows.AuthorizationCode.AuthorizationUrl = new Uri(securityScheme.Value.Flows.AuthorizationCode.AuthorizationUrl.ToString().Replace("ids", $"{_currentTenant.Name}.ids"));
                    securityScheme.Value.Flows.AuthorizationCode.TokenUrl = new Uri(securityScheme.Value.Flows.AuthorizationCode.TokenUrl.ToString().Replace("ids", $"{_currentTenant.Name}.ids"));
    
                }
            }
    
            return _innerSwaggerGenerator.GetSwagger(documentName, host, basePath);
        }
    }
    
    
    
  • User Avatar
    0
    sh_erfan created

    Thanks a lot This solved the problem Better to update sample to avoid future duplicate questions

Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11