首页 > 解决方案 > 将 Web 应用身份验证转发到 API 服务

问题描述

我有一个应用程序被分解成一个 Web 应用程序(Asp .net MVC),它与一个用 C# .net core 2.2 编写的 API 服务对话。我有使用内置 AZure AD 身份验证的 Web 应用程序。这很好用,因为它会提示用户输入他们的 Azure 域 ID 和密码,并且只允许特定用户进入。

我对 API 服务做了同样的事情。所有的 startup.cs 代码都已正确设置。

我想使用来自 web 应用程序的身份验证并转发到 api 服务,但无法找到一种方法来做到这一点,甚至无法访问它。

我尝试添加不同的身份验证方案(azureadbearer 和 jwtbearer),但这些方案只是让 Web 应用程序无法工作,从未提示进行身份验证

在 Web 应用程序中,这使用 Azure AD 并要求对用户进行身份验证:

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
  .AddAzureAD(options =>
  {
       Configuration.Bind("AzureAd", options);
  });

在 API 服务中,我有

services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
      .AddAzureADBearer(options => Configuration.Bind("AzureAd", options));

但我无法弄清楚网络应用程序应该如何/调用什么来授权或获取 api 服务的令牌。如果我为 api 控制器添加 [Authorize] 属性,我会从 Web 应用程序调用它时收到未经授权的错误。

我希望能够使用或获取在用户授权 Web 应用程序并将其转发到 api 服务时创建的令牌,但在标头中没有看到任何类似于 jwt 令牌的内容。

我还尝试在 Web 应用程序中创建 jwt 令牌并设置授权标头(承载令牌)并发送到 api 服务,并将 api 服务更改为使用 jwtbearer,但我仍然会得到未经授权的。

我花了几天的时间试图找到示例并让这个工作没有运气,任何建议都将不胜感激......希望能够使用内置的 AzureAD 中间件,如果可能的话,不必编写任何代码来处理这个问题。

这是我在 api 服务中尝试过的,但没有验证我发送的令牌:s

services.AddAuthentication(AzureADDefaults.JwtBearerAuthenticationScheme).AddJwtBearer(cfg =>
  {
      cfg.RequireHttpsMetadata = true;
      cfg.SaveToken = true;
      cfg.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
      {
          ValidIssuer = Configuration["ServiceAd:Issuer"],
          ValidAudience = Configuration["ServiceAd:Audience"],
          IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["ServiceAd:ClientSecret"]))
      };
  });

标签: c#.netauthenticationazure-active-directoryasp.net-core-2.2

解决方案


我建议使用OAuth2.0 代表 flow。根据您的要求,您希望在 Web 应用程序中对用户进行身份验证,并为 Web api 创建一个令牌并从 Web 应用程序控制器调用 Web api。

首先创建 2 个服务主体,一个用于 web 应用程序,第二个用于 web api。然后转到 web 应用服务主体 --> 权限部分并添加 web api(服务主体)并授予权限。

创建服务主体后,您需要在 Web 应用控制器中使用 OAuth 2.0 代流。运行 Web 应用程序后,您必须使用用户名和密码对用户进行身份验证,在对用户进行身份验证后,您可以在控制器操作方法中使用 HttpContext 获取 access_token,然后使用代表流程获取另一个令牌web api 并调用 web api 来访问资源。

您可以查看以下代流文档: OAuth2.0 代流

在 web app--> HomeController.cs --> Index() 方法中获取当前令牌(第一次登录时获取访问令牌),使用该令牌为 web api 创建另一个令牌。

以下是代表流程的代码:

 private async Task<string> GetOnBehalfToken()
    {
        // Get User Assertion
        var authenticateInfo = await HttpContext.Authentication.GetAuthenticateInfoAsync("Bearer");
        string incomingToken = authenticateInfo.Properties.Items[".Token.access_token"];
        UserAssertion userAssertion = new UserAssertion(incomingClientToken, "urn:ietf:params:oauth:grant-type:jwt-bearer");

        string token = string.Empty;
        string authString = string.Format(this.azureAd.AadInstance, this.azureAd.TenantId);
        AuthenticationContext authenticationContext = new AuthenticationContext(authString, false);

        // config for oauth client credentials
        // Use Web app client id and secret key
        ClientCredential clientCredential = new ClientCredential(this.azureAd.ClientId, this.azureAd.AppKey);

        // App ID uri of web api service principal
        var resource = "https://<tenant>.onmicrosoft.com/45854ee0-608a-4dff-xxx-xxxxxxxxxxx";

        AuthenticationResult result = await authenticationContext.AcquireTokenAsync(resource, clientCredential);
        return result.AccessToken;
    }

获取 web api 的令牌后,将其添加到 http 客户端的 Authorization 标头并调用 api。

如果您只想使用 Azure AD 对 Web api 进行身份验证。在启动时使用下面的代码,看看它是否适合你:

public static void ConfigureAuthentication(IAppBuilder app)
    {
        app.UseWindowsAzureActiveDirectoryBearerAuthentication(
           new WindowsAzureActiveDirectoryBearerAuthenticationOptions
           {
               Tenant = Configuration["AzureAD.TenantId"],
               TokenValidationParameters = new TokenValidationParameters()
               {
                   ValidateIssuer = true,
                   ValidIssuer = Configuration["AzureAD.Issuer"],
                   ValidAudience = Configuration["AzureAD.Audience"],
                   ValidateLifetime = true
               }
           });

        app.UseJwtBearerAuthentication(
            new JwtBearerAuthenticationOptions
            {
                AuthenticationMode = AuthenticationMode.Active,
                TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuer = true,
                    ValidIssuer = Configuration["AzureAD.Issuer"],
                    ValidAudience = Configuration["AzureAD.Audience"],
                    ValidateLifetime = true
                }
            });
    }

还要验证 Issuer({tenant-name}.onmicrosoft.com) 和 Audience(App Id uri of service principal) 值是否正确。

我希望这能解决你的问题。


推荐阅读