【问题标题】:Azure Billing Usage API returns 401 UnauthorizedAzure 计费使用 API 返回 401 Unauthorized
【发布时间】:2016-04-05 22:08:22
【问题描述】:

我正在使用 Azure REST API 来获取计费使用情况和费率卡详细信息。 要使用 AcquireToken() 方法获取 Token,最初我只使用 Client Id,然后在登录窗口中询问用户凭据。

但是,我正在寻找 非交互式方法,因此我使用了 Client Credentials,其中我传递了 Client Id客户端密钥

但它给出了“远程服务器返回错误 401 Unauthorized”

当我深入查看错误时,我发现它给出了错误“访问令牌来自错误的受众或资源”

请给我任何解决方案,让我无需任何用户交互即可访问 API。

提前致谢。

这是我的代码:

{
    string token = GetOAuthTokenFromAAD();
    string requestURL = String.Format("{0}/{1}/{2}/{3}",
                   ConfigurationManager.AppSettings["ARMBillingServiceURL"],
                   "subscriptions",
                   ConfigurationManager.AppSettings["SubscriptionID"],
                   "providers/Microsoft.Commerce/RateCard?api-version=2015-06-01-preview&$filter=OfferDurableId eq 'MS-AZR-*****' and Currency eq 'INR' and Locale eq 'en-IN' and RegionInfo eq 'IN'");

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestURL);

    request.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + token);
    request.ContentType = "application/json";
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    Console.WriteLine(String.Format("RateCard service response status: {0}", response.StatusDescription));
}

public static string GetOAuthTokenFromAAD()
{
      AuthenticationContext authenticationContext = new AuthenticationContext(string.Format("{0}/{1}",ConfigurationManager.AppSettings["ADALServiceURL"], ConfigurationManager.AppSettings["TenantDomain"]));

      AuthenticationResult result = null;
      ClientCredential uc = new ClientCredential(Client_Id, Secret_Key);
      try
      {
           result = authenticationContext.AcquireToken("https://management.core.windows.net/", uc);
      } 
      return result.AccessToken;
}

//App Config File
<add key="ADALServiceURL" value="https://login.microsoftonline.com" />
<add key="ADALRedirectURL" value="http://*****-authentication.cloudapp.net" />
<add key="ARMBillingServiceURL" value="https://management.core.windows.net" />
<add key="TenantDomain" value="********.onmicrosoft.com" />
<add key="SubscriptionID" value="*******-****-****-****-********" />
<add key="ClientId" value="*******-****-****-****-********" />

【问题讨论】:

  • 请分享您的代码以及您在 Azure AD 中创建的应用程序的设置。
  • 一个快速的问题 - 在 Azure AD 中配置应用程序时,您是否添加了执行服务管理 API 操作的权限?
  • 是的。我已将 Windows Azure 服务管理权限提供为访问 Azure 服务管理(预览版),这是委派权限下下拉菜单中唯一可用的选项。
  • 最后一个问题(很抱歉以零碎的方式提出这些问题)- 在 Azure AD 中创建应用程序时,您选择了 Web 应用程序。正确的?让我尝试在我的 Azure AD 中做同样的事情,看看我是否可以重现这种行为。
  • 请参阅此链接:azure.microsoft.com/en-in/documentation/articles/…。您需要在订阅级别执行此操作。此外,由于您遇到了与“观众”相关的错误,因此在令牌中看到观众并没有什么坏处。在您的代码中执行以下操作:System.IdentityModel.Tokens.JwtSecurityToken securityToken = new System.IdentityModel.Tokens.JwtSecurityToken(token);,然后检查 securityToken 中的Audiences 属性。请看截图:i.stack.imgur.com/j4RWS.png

标签: c# azure azure-billing-api


【解决方案1】:

更新:我还提供了这些方法作为可重用的身份验证助手类库。您可以在此链接中找到相同的内容: Azure Authentication - Authenticating any Azure API Request in your Application

方法 1: 要以非交互方式使用密码方法,您需要首先遵循以下帖子的“使用密码进行身份验证 - PowerShell”部分: Authenticating a service principal with ARM

然后使用下面的代码 sn-p 来获取令牌。

var authenticationContext = new AuthenticationContext(String.Format("{0}/{1}",
                                                                ConfigurationManager.AppSettings["ADALServiceURL"],
                                                                ConfigurationManager.AppSettings["TenantDomain"]));
        var credential = new ClientCredential(clientId: "11a11111-11a1-111a-a111-1afeda2bca1a", clientSecret: "passwordhere");
        var result = authenticationContext.AcquireToken(resource: "https://management.core.windows.net/", clientCredential: credential);

        if (result == null)
        {
            throw new InvalidOperationException("Failed to obtain the JWT token");
        }

        string token = result.AccessToken;

        return token;

或者(方法2),您也可以使用证书方法。在这种情况下,请使用与上述相同的链接,但请按照该链接中的“使用证书进行身份验证 - PowerShell”部分进行操作。然后使用下面的代码 sn-p 以非交互方式获取令牌:

 var subscriptionId = "1a11aa11-5c9b-4c94-b875-b7b55af5d316";
        string tenant = "1a11111a-5713-4b00-a1c3-88da50be3ace";
        string clientId = "aa11a111-1050-4892-a2d8-4747441be14d";

        var authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}", tenant));

        X509Certificate2 cert = null;
        X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        string certName = "MyCert01";

        try
        {
            store.Open(OpenFlags.ReadOnly);
            var certCollection = store.Certificates;
            var certs = certCollection.Find(X509FindType.FindBySubjectName, certName, false);
            //var certs = certCollection.Find(X509FindType.FindBySerialNumber, "E144928868B609D35F72", false);
            if (certs == null || certs.Count <= 0)
            {
                throw new Exception("Certificate " + certName + " not found.");
            }
            cert = certs[0];
        }
        finally
        {
            store.Close();
        }

        var certCred = new ClientAssertionCertificate(clientId, cert);
        var token = authContext.AcquireToken("https://management.core.windows.net/", certCred);
        var creds = new TokenCloudCredentials(subscriptionId, token.AccessToken);
        //var client = new ResourceManagementClient(creds); 
        return token.AccessToken;

【讨论】:

    猜你喜欢
    • 2020-01-01
    • 1970-01-01
    • 2015-08-13
    • 2015-03-13
    • 2021-09-02
    • 2023-03-14
    • 1970-01-01
    • 2021-10-19
    • 2013-04-05
    相关资源
    最近更新 更多