【问题标题】:Execution works with personal access token, but not using AAD access token for Azure DevOps执行适用于个人访问令牌,但不适用于 Azure DevOps 的 AAD 访问令牌
【发布时间】:2020-01-04 17:59:42
【问题描述】:

我的以下代码以 JSON 格式从 Azure DevOps 存储库输出主分支统计信息,我正在捕获所需的输出。这在我使用个人访问令牌时起作用,身份验证起作用并从 API 中返回结果。

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

StatusCode:203,ReasonPhrase:“非权威信息”,版本: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;
}

使用上面代码生成的访问令牌尝试使用邮递员进行测试,得到如下截图。

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

【问题讨论】:

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


【解决方案1】:

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

试试下面的代码:

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

更新:

  1. 注册新应用

  2. 默认将应用设置为公共客户端

  3. 向 DevOps API 添加权限

  4. 新建项目,安装Microsoft.IdentityModel.Clients.ActiveDirectory

  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();
        }
    }
}

【讨论】:

  • 我仍然得到相同的响应 :-(
  • 您不能使用客户端凭据流。您需要以用户身份签名。稍后查看我的更新。
  • 感谢您提供详细信息。我会尝试这个,但不确定关于我如何在默认情况下禁用汽车的授权部分。目前为应用添加了 Azure devOps API 权限。会及时通知您。
  • 该按钮用于管理员授予整个租户的同意。由于 DevOps API 权限是用户自己同意的,所以可以使用一次交互式登录。这将仅授予用户同意。
  • 完美!我必须获得我的组织批准才能获得管理员同意,这解决了我的问题。您一直是任何人都可以轻松理解的正确指示的最佳帮助。非常感谢您抽出宝贵时间提供帮助。
猜你喜欢
  • 2021-11-15
  • 2021-12-24
  • 2019-09-26
  • 2015-11-03
  • 2020-08-31
  • 2020-07-27
  • 1970-01-01
  • 2018-12-06
  • 1970-01-01
相关资源
最近更新 更多