执行使用个人访问令牌,但不适用于Azure DevOps使用AAD访问令牌

时间:2019-09-01 08:27:28

标签: c# azure-active-directory access-token azure-devops-rest-api

我有下面的代码,这些代码从Azure DevOps存储库以JSON格式输出主分支统计信息,并且正在捕获所需的输出。当我使用个人访问令牌进行身份验证并从API返回结果时,此方法有效。

但是,当我尝试使用AAD中的已注册应用程序生成访问令牌(已在API权限下为Azure DevOps启用委派的用户模拟)时,我能够生成访问令牌,然后在调用API时将其传递返回

  

状态码:203,原因短语:“非权威信息”,版本:1.1,内容:System.Net.Http.StreamContent

public static async Task GetBuilds()
{
    string url = "Azure Dev-Ops API";
    var personalaccesstoken = "personalaccesscode";
    //var personalaccesstoken = token.GetYourTokenWithClientCredentialsFlow().Result;
    string value = null;

using (HttpClient client = new HttpClient())
{
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", personalaccesstoken))));
    using (HttpResponseMessage response = await client.GetAsync(url))
    {
        response.EnsureSuccessStatusCode();
        string responseBody = await response.Content.ReadAsStringAsync();
        dynamic jsonObject = JsonConvert.DeserializeObject(responseBody);
        value = jsonObject;
    }
}

if (value != null)
{
    Console.WriteLine(value);
}
}

public static async Task<string> GetYourTokenWithClientCredentialsFlow()
{
    string tokenUrl = $"https://login.microsoftonline.com/{tenant ID}/oauth2/token";
    var tokenRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);

    tokenRequest.Content = new FormUrlEncodedContent(new Dictionary<string, string>
    {
        ["grant_type"] = "client_credentials",
        ["client_id"] = "client ID",
        ["client_secret"] = "client secret",
        ["resource"] = "https://graph.microsoft.com/"
    });

    dynamic json;
    dynamic token;
    string accessToken;

    HttpClient client = new HttpClient();

    var tokenResponse = client.SendAsync(tokenRequest).Result;
    json = await tokenResponse.Content.ReadAsStringAsync();
    token = JsonConvert.DeserializeObject(json);
    accessToken = token.access_token;
    return accessToken;
}

尝试使用邮递员使用上面的代码生成的访问令牌进行测试,并获得以下屏幕截图。

enter image description here

我在这里做错什么,如何解决该问题?

1 个答案:

答案 0 :(得分:2)

天蓝色广告访问令牌是不记名令牌。您无需将其用作基本身份验证。

尝试以下代码:

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", GetYourTokenWithClientCredentialsFlow().Result);

更新

  1. 注册一个新应用 enter image description here

  2. 默认情况下将应用设置为公共客户端 enter image description here

  3. 向DevOps API添加权限 enter image description here

  4. 创建一个新项目,安装 Microsoft.IdentityModel.Clients.ActiveDirectory 程序包 enter image description here

  5. 代码示例

class Program
{
    static string azureDevOpsOrganizationUrl = "https://dev.azure.com/jack0503/"; //change to the URL of your Azure DevOps account; NOTE: This must use HTTPS
    static string clientId = "0a1f****-****-****-****-a2a4****7f69";          //change to your app registration's Application ID
    static string replyUri = "https://localhost/";                     //change to your app registration's reply URI
    static string azureDevOpsResourceId = "499b84ac-1321-427f-aa17-267ca6975798"; //Constant value to target Azure DevOps. Do not change  
    static string tenant = "hanxia.onmicrosoft.com";     //your tenant ID or Name
    static String GetTokenInteractively()
    {
        AuthenticationContext ctx = new AuthenticationContext("https://login.microsoftonline.com/" + tenant); ;
        IPlatformParameters promptBehavior = new PlatformParameters(PromptBehavior.Auto | PromptBehavior.SelectAccount);
        AuthenticationResult result = ctx.AcquireTokenAsync(azureDevOpsResourceId, clientId, new Uri(replyUri), promptBehavior).Result;
        return result.AccessToken;
    }

    static String GetToken()
    {
        AuthenticationContext ctx = new AuthenticationContext("https://login.microsoftonline.com/" + tenant); ;
        UserPasswordCredential upc = new UserPasswordCredential("jack@hanxia.onmicrosoft.com", "yourpassword");
        AuthenticationResult result = ctx.AcquireTokenAsync(azureDevOpsResourceId, clientId, upc).Result;
        return result.AccessToken;
    }
    static void Main(string[] args)
    {
        //string token = GetTokenInteractively();
        string token = GetToken();

        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri(azureDevOpsOrganizationUrl);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

            HttpResponseMessage response = client.GetAsync("_apis/projects").Result;

            if (response.IsSuccessStatusCode)
            {
                Console.WriteLine("\tSuccesful REST call");
                var result = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine(result);
            }
            else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
            {
                throw new UnauthorizedAccessException();
            }
            else
            {
                Console.WriteLine("{0}:{1}", response.StatusCode, response.ReasonPhrase);
            }

            Console.ReadLine();
        }
    }
}