Azure web api未经授权401

时间:2017-03-29 16:01:58

标签: api azure authentication

我有一些代码用于调用Azure Scheduler获取令牌,然后使用该令牌进行休息调用。是一种享受。

所以我决定将代码应用到一个新的应用程序中,但这次调用我自己的web api托管在azure上。 API在Active目录中注册我创建了一个密钥等。当我初始化我的静态httpclient时,它成功获取了一个令牌。

但是当我使用令牌进行身份验证调用API时,响应是401"未授权",下面是代码。

 public static class SchedulerHttpClient
{
    const string SPNPayload = "resource={0}&client_id={1}&grant_type=client_credentials&client_secret={2}";

    private static Lazy<Task<HttpClient>> _Client = new Lazy<Task<HttpClient>>(async () =>
    {
        string baseAddress = ConfigurationManager.AppSettings["BaseAddress"];
        var client = new HttpClient();
        client.BaseAddress = new Uri(baseAddress);
        await MainAsync(client).ConfigureAwait(false);
        return client;
    });

    public static Task<HttpClient> ClientTask => _Client.Value;

    private static async Task MainAsync(HttpClient client)
    {
        string tenantId = ConfigurationManager.AppSettings["AzureTenantId"];
        string clientId = ConfigurationManager.AppSettings["AzureClientId"];
        string clientSecret = ConfigurationManager.AppSettings["AzureClientSecret"];

        string token = await AcquireTokenBySPN(client, tenantId, clientId, clientSecret).ConfigureAwait(false);

        client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); //TODO ssmith: const or localization
    }

    private static async Task<string> AcquireTokenBySPN(HttpClient client, string tenantId, string clientId, string clientSecret)
    {
        var payload = String.Format(SPNPayload,
                                    WebUtility.UrlEncode(ConfigurationManager.AppSettings["ARMResource"]),
                                    WebUtility.UrlEncode(clientId),
                                    WebUtility.UrlEncode(clientSecret));

        var body = await HttpPost(client, tenantId, payload).ConfigureAwait(false);
        return body.access_token;
    }

    private static async Task<dynamic> HttpPost(HttpClient client, string tenantId, string payload)
    {
        var address = String.Format(ConfigurationManager.AppSettings["TokenEndpoint"], tenantId);
        var content = new StringContent(payload, Encoding.UTF8, "application/x-www-form-urlencoded");
        using (var response = await client.PostAsync(address, content).ConfigureAwait(false))
        {
            if (!response.IsSuccessStatusCode)
            {
                Console.WriteLine("Status:  {0}", response.StatusCode);
                Console.WriteLine("Content: {0}", await response.Content.ReadAsStringAsync().ConfigureAwait(false));
            }//TODO: start removing tests

            response.EnsureSuccessStatusCode();

            return await response.Content.ReadAsAsync<dynamic>().ConfigureAwait(false);
        }
    }
}

上面的代码是创建httpclient并获得其授权的类。

public virtual async Task<T> GetAsync(string apiURL)
    {
        try
        {
            _client = await SchedulerHttpClient.ClientTask;
            var response = await _client.GetAsync(apiURL);
            response.EnsureSuccessStatusCode();
            var responseContent = await response.Content.ReadAsAsync<T>().ConfigureAwait(false);

            return responseContent;
        }
        catch (Exception e)
        {
            return default(T);
        }
    }

上面的代码是我的旧代码的快速提升,只是为了测试我是否可以获得任何结果。但正如所述,它返回401。

我的问题是,我的旧代码是不正确的授权?

<add key="ARMResource" value="https://management.core.windows.net/" />
<add key="TokenEndpoint" value="https://login.windows.net/{0}/oauth2/token" />
<add key="BaseAddress" value="https://mysite.azurewebsites.net" />

1 个答案:

答案 0 :(得分:0)

如所怀疑的那样,这个特殊问题是由于在网络API的情况下错误的“ARMresource”导致我需要将其更改为客户端ID。

Source of answer

似乎我的问题是一样的,但我怀疑我可以完全从我的SPNPayload字符串中省略资源。