如何从Azure OAuth 2.0令牌(v2)端点获取/生成访问令牌?

时间:2019-05-17 04:54:25

标签: c# azure azure-devops azure-active-directory

我想从给定的URL获取访问令牌:

https://login.microsoftonline.com/{AzureTenantId}/oauth2/v2.0/token

我正在传递以下参数,如Microsoft文档中所述: client_idscopeclient_secretgrant_type

点击此URL时,我会收到“ 400错误的请求”响应。

当我从Postman尝试相同的操作时,它会成功并为我提供访问令牌:

success postman request

但不是来自我的代码:

public async Task<string> GetAuthorizationToken(string clientId, string ServicePrincipalPassword, string AzureTenantId) {
            var result = "";
            var requestURL = "https://login.microsoftonline.com/{AzureTenantId}/oauth2/v2.0/token";
            var _httpClient = new HttpClient();

            var model = new {
                client_id = clientId,
                scope = "{clentID}/.default",
                client_secret = ServicePrincipalPassword,
                grant_type = "client_credentials"
            };

            HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(model), System.Text.Encoding.UTF8, "application/x-www-form-urlencoded");

            var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri(requestURL)) {
                Content = httpContent
            };

            using (var response = await _httpClient.SendAsync(httpRequestMessage)) {
                if (response.IsSuccessStatusCode) {
                    var responseStream = await response.Content.ReadAsStringAsync();
                    return result;
                } else {
                    return result;
                }
            }

3 个答案:

答案 0 :(得分:3)

您的http请求格式不正确,请尝试:

var _httpClient = new HttpClient();

var content = new FormUrlEncodedContent(new Dictionary<string, string> {
              { "client_id", "ClientID" },
              { "client_secret", "YourSecret" },
              { "grant_type", "client_credentials" },
              { "scope", "https://graph.microsoft.com/.default" },
            });

var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri(requestURL))
{
    Content = content
};

using (var response = await _httpClient.SendAsync(httpRequestMessage))
{
    if (response.IsSuccessStatusCode)
    {
        var responseStream = await response.Content.ReadAsStringAsync();
        return result;
    }
    else
    {
        return result;
    }
}

答案 1 :(得分:1)

遵循这些步骤

  1. 转到应用程序的“公开Api”刀片。
  2. 找到应用ID URI值。假设应用ID Uri为http://abc.pqr
  3. 您用于获取令牌的资源将是http://abc.pqr/.default

答案 2 :(得分:1)

作为Nan Yu's answer的补充,您可能要考虑为此使用库,而不是尝试自己实现。

例如,使用.NET的Microsoft身份验证库(MSAL),您将获得如下访问令牌:

// Setup MSAL
var client = ConfidentialClientApplicationBuilder
    .Create("{client-id}")
    .WithAuthority("https://login.microsoftonline.com/{tenant-id}/v2.0")
    .WithClientSecret(/* retrieve from secure storage, do *NOT* put the secret in your code! */)
    .Build();

// Retrieve an access token
var scopes = new string[] { "https://graph.microsoft.com/.default" };
var authResult = await clientApplication.AcquireTokenForClient(scopes).ExecuteAsync();

// The access token is in $authResult.AccessToken

一个重要的优点是,您无需担心跟踪令牌的有效性来知道何时需要获取新令牌。如果需要获取新令牌,只需再次调用AcquireTokenForClient,它将为您确定是否需要新令牌,或者是否可以使用已缓存的令牌。