如何代表流在.Net Core中调用下游API?

Posted

技术标签:

【中文标题】如何代表流在.Net Core中调用下游API?【英文标题】:How to call downstream API in .Net Core using on behalf of flow? 【发布时间】:2021-08-12 19:38:10 【问题描述】:

Net 核心应用程序和反应。我有调用我的中间层 api 和中间层 api 调用下游 api 的反应应用程序。我在 azure ad 中注册了三个应用程序。我已经做了所有的配置。在中间层 API 中,我正在验证从反应应用程序收到的令牌并尝试获取下游 api 的令牌,如下所示。

public void ConfigureServices(IServiceCollection services)
        
            services.AddControllers();
            services.AddTransient<DownStreamAPIService>();
            services.AddHttpClient();
            services.AddOptions();
            var azureAd = Configuration.GetSection("AzureAd").Get<AzureAd>();
            IdentityModelEventSource.ShowPII = true;

            services.AddMicrosoftIdentityWebApiAuthentication(Configuration)
                .EnableTokenAcquisitionToCallDownstreamApi()
                .AddInMemoryTokenCaches();

            services.AddAuthentication(x =>
            
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            )
            .AddJwtBearer(options =>
            
                options.SaveToken = true;
                options.RequireHttpsMetadata = true;
                options.Authority = $"azureAd.Instance/azureAd.TenantId/v2.0";
                options.Audience = $"azureAd.ClientId";

                options.TokenValidationParameters = new TokenValidationParameters
                
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuer = true,
                    ValidateIssuerSigningKey = false,
                    ValidateActor = false
                ;
            );

            services.AddCors(options =>
            
                options.AddPolicy(
                    "CorsPolicy",
                    builder =>
                    
                        builder
                        .WithOrigins("https://localhost:3000")
                            .AllowAnyHeader()
                            .AllowAnyMethod()
                            .AllowCredentials();
                    );
            );
         

下面是 DownStreamAPIService 类

public async Task<JArray> GetApiDataAsync()
        
            var client = _clientFactory.CreateClient();

            // user_impersonation access_as_user access_as_application .default
            var scope = _configuration["DownStreamAPI:ScopeForAccessToken"];
            var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new[]  scope ).ConfigureAwait(false);

            client.BaseAddress = new Uri(_configuration["DownStreamAPI:ApiBaseAddress"]);
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            var response = await client.GetAsync("weatherforecast").ConfigureAwait(false);
            if (response.IsSuccessStatusCode)
            
                var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                var data = JArray.Parse(responseContent);

                return data;
            

            throw new ApplicationException($"Status code: response.StatusCode, Error: response.ReasonPhrase");
        

下面是appsettings.json文件

 "AzureAd": 
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "mydomain.onmicrosoft.com",
    "TenantId": "c5fff990-0e0a-4bf6-9c04-79ab98e05931",
    "ClientId": "43dg8b3c-8743-4d6e-84b4-00fe04d93222"
  ,
  "WebOriginUrl": "https://localhost:3000",
  "DownStreamAPI": 
    "ScopeForAccessToken": "api://723fac69-4038-4e16-92cc-3f57b7cc2381/access_downstream_api_as_user",
    "ApiBaseAddress": "https://localhost:44316"
  

当我运行应用程序时出现以下错误

方案已经存在:Bearer

在我的中间层应用程序中,我正在验证令牌并尝试为下游 API 获取新令牌。我只是对中间层 api 中是否需要天气验证令牌感到困惑。我代表流量使用。如果此设计有任何问题,可以提供帮助。任何帮助,将不胜感激。谢谢

【问题讨论】:

【参考方案1】:

当我们使用AddMicrosoftIdentityWebApiAuthentication 配置Azure AD 时,项目将使用Bearer 方案进行身份验证。我们不需要再次配置它。更多详情请参考here和here。所以请删除代码

services.AddAuthentication(x =>
            
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            )
            .AddJwtBearer(options =>
            
                options.SaveToken = true;
                options.RequireHttpsMetadata = true;
                options.Authority = $"azureAd.Instance/azureAd.TenantId/v2.0";
                options.Audience = $"azureAd.ClientId";

                options.TokenValidationParameters = new TokenValidationParameters
                
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuer = true,
                    ValidateIssuerSigningKey = false,
                    ValidateActor = false
                ;
            );

如果要验证token,可以使用以下代码

 services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
            
                options.SaveToken = true;
                options.RequireHttpsMetadata = true;

                options.TokenValidationParameters = new TokenValidationParameters
                
                    ValidateAudience = true,
                    ValidAudiences = new string[]  "872ebcec-c24a-4399-835a-201cdaf7d68b", "api://872ebcec-c24a-4399-835a-201cdaf7d68b" ,
                    ValidateLifetime = true,
                    ValidateIssuer = true,
                    ValidateIssuerSigningKey = false,
                    ValidateActor = false,
                    ValidIssuers = new string[]  "https://sts.windows.net/tenantId", "https://login.microsoftonline.com/tenantId/v2.0" 
                ;
            );

【讨论】:

以上是关于如何代表流在.Net Core中调用下游API?的主要内容,如果未能解决你的问题,请参考以下文章

如何用 ASP.NET Core 实现熔断和降级?

如何在 IdentityServer ASP.NET Core 中使用 Postman 使用 AntiForgeryToken 调用 API

如何在 .net Core API 项目中跨多个线程限制对 HttpClient 的所有传出异步调用

无论用户登录如何,如何保护 Angular / .NET Core 2.0 应用程序中的所有 api 调用

将 Charles Proxy 与 .NET Core Azure 站点一起使用 - 如何查看 API 调用?

如何在 .NET Core Web API 中配置并发?