【问题标题】:401 error when authenticating to an Azure API App using AAD使用 AAD 对 Azure API 应用程序进行身份验证时出现 401 错误
【发布时间】:2016-03-22 22:41:49
【问题描述】:

我有一个 API 应用程序在网关主机上运行良好,现在网关主机已被弃用,我正在尝试关注 Migration Guide。我已经使用 2.8.1 SDK 重新部署了我的服务,并且可以使用 AAD 或 Microsoft 帐户使用浏览器登录该服务,并使用 Swagger 测试该服务。但是,我试图让客户端使用 ClientId 和 Secret 访问服务。该代码能够从 AAD 获取访问令牌,但每当我尝试访问其中一项服务资源时,总是会收到 401 错误。

当我调试服务时,我在日志中看到以下内容:

Microsoft.Azure.AppService.Authentication Verbose: 0 : Received request: GET https://[myService].azurewebsites.net/api/[myResource]
Microsoft.Azure.AppService.Authentication Warning: 0 : JWT validation failed: IDX10214: Audience validation failed. Audiences: 'https://[myService].azurewebsites.net/'. Did not match:  validationParameters.ValidAudience: '[AAD ClientId]' or validationParameters.ValidAudiences: 'http://[myService].azurewebsites.net'.
Microsoft.Azure.AppService.Authentication Information: 0 : Sending response: 401.71 Unauthorized
The thread 0x3b00 has exited with code 0 (0x0).

问题似乎在于,请求的受众是 https,但 validParameters.ValidAudiences 集合仅包含 http。

我看不到任何配置受众的方式,并且似乎在 Visual Studio 2015 创建应用服务时正在设置基于 http 的受众。有没有手动编辑 ValidAudience 集合的方法?

作为参考,我的客户端代码是:

    private static void Main(string[] args)
    {
        string app_id_url = "https://[myService].azurewebsites.net/";
        string authority = "https://login.windows.net/[myDirectory].onmicrosoft.com/";
        string clientId = "[AAD ClientId]";
        string clientSecret = "[AAD Client Secret]";
        string apiBaseUrl = "https://[myService].azurewebsites.net/";

        string aadToken = GetTokenForApplication(authority, clientId, clientSecret, app_id_url);

        var apiClient = new HttpClient { BaseAddress = new Uri(apiBaseUrl) };
        apiClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", aadToken);
        var apiResponse = apiClient.GetAsync(apiBaseUrl + @"api/[myResource]").Result;
        string apiResponseContent = apiResponse.Content.ReadAsStringAsync().Result;
        Console.WriteLine(apiResponseContent);
    }

    public static string GetTokenForApplication(string authority, string clientId, string clientSecret, string resourceUrl)
    {
        AuthenticationContext authenticationContext = new AuthenticationContext(authority, false);
        ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
        AuthenticationResult authenticationResult = authenticationContext.AcquireToken(resourceUrl, clientCred);
        string token = authenticationResult.AccessToken;
        return token;
    }

【问题讨论】:

  • 您需要将方括号之间的标识符替换为部署中的实际参数。
  • 感谢@MvdD,但出于本文的目的,我删除了实际参数。正如您从帖子顶部看到的那样,这曾经可以工作,但现在不行了。
  • 嗨@GraemeWilson,您还需要回答这个问题还是找到解决方案?
  • @juvchan 我在 Azure 门户中手动创建了一个空的应用服务,然后手动向 AAD 注册了该应用。然后我使用 VS 2015 将我的应用程序发布到应用程序服务。这似乎有效并且服务正确地验证了客户端。我在进行了很多修改后才开始使用它,而且我还没有时间准确地重现这些步骤,所以不要把它当作一个明确的解决方法。但 VS 2015 发布到 App Services 的方式似乎确实存在问题。
  • 您是否使用第二个 Azure 应用程序来验证本机客户端?

标签: c# azure azure-active-directory adal azure-api-apps


【解决方案1】:

在我的 ASP.NET 4.5 Web 应用程序中,我发现我必须指定有效受众以避免引发运行时异常。

public partial class Startup
{
    private static string _aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
    private static string _tenant = ConfigurationManager.AppSettings["ida:Tenant"];
    private static string _realm = ConfigurationManager.AppSettings["ida:Wtrealm"];
    private static string _metadataAddress = string.Format("{0}/{1}/federationmetadata/2007-06/federationmetadata.xml", _aadInstance, _tenant);
    private static string _authority = String.Format(CultureInfo.InvariantCulture, _aadInstance, _tenant);

    public void ConfigureAuth(IAppBuilder app)
    {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        app.UseWsFederationAuthentication(
            new WsFederationAuthenticationOptions
            {
                Wtrealm = _realm,
                MetadataAddress = _metadataAddress,
                TokenValidationParameters = new TokenValidationParameters
                {
                    ValidAudiences = new string[] { "spn:" + _realm }
                }
            }
        );
    }
}

【讨论】:

    【解决方案2】:

    您的问题与有效受众有关。您可能有 2 个选择:

    选项 1. 尝试使用 WebAPI 客户端 ID 作为 AcquireToken 方法的“资源”参数而不是其 Uri 获取令牌。

    选项 2。如果以前的方法不起作用,您应该使用 Azure Resources Explorer 修改应用服务 API 的身份验证设置。导航到您的 Web API,在 config 节点下找到 authSettings JSON 文档,然后修改(在更改为读/写模式后)数组 allowedAudiences 以满足您的需要。在您的情况下,您可能需要将 http 更改为 https

    【讨论】:

    • 我还要补充一点,当 Loul 说“导航到您的 Web API”时,他的意思是您应该使用资源浏览器顶部的搜索框。如果您在搜索之前开始扩展提供程序和订阅,那么它似乎不起作用。最终我在 subscriptions/mysubname/resourceGroups/myresourcegroupname/providers/Microsoft.Web/sites 下找到了我的 API
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 1970-01-01
    • 2012-10-06
    • 2015-11-28
    • 2017-10-23
    • 2015-12-16
    相关资源
    最近更新 更多