执行适用于个人访问令牌,但不适用于 Azure DevOps 的 AAD 访问令牌
Execution works with personal access token, but not using AAD access token for Azure DevOps
我有以下代码,它以 JSON 格式从 Azure DevOps 存储库输出主分支统计信息,我正在捕获所需的输出。这在我使用个人访问令牌时有效,身份验证有效并返回 API 的结果。
但是当我尝试使用 AAD 中注册的应用程序生成访问令牌时(在 API 权限下为 Azure DevOps 启用了委托用户模拟),我能够生成访问令牌,然后在传递它的同时调用 API,但它 returns 返回
StatusCode: 203, ReasonPhrase: 'Non-Authoritative Information', Version: 1.1, Content: 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;
}
尝试使用邮递员使用上述代码生成的访问令牌进行测试,并获得如下截图。
我在这里做错了什么,我该如何解决这个问题?
azure 广告访问令牌是不记名令牌。您不需要将其用作基本身份验证。
尝试使用以下代码:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", GetYourTokenWithClientCredentialsFlow().Result);
更新:
注册一个新应用
默认将应用设置为 public 客户端
添加 DevOps 权限 API
新建项目,安装Microsoft.IdentityModel.Clients.ActiveDirectory包
代码示例
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();
}
}
}
我有以下代码,它以 JSON 格式从 Azure DevOps 存储库输出主分支统计信息,我正在捕获所需的输出。这在我使用个人访问令牌时有效,身份验证有效并返回 API 的结果。
但是当我尝试使用 AAD 中注册的应用程序生成访问令牌时(在 API 权限下为 Azure DevOps 启用了委托用户模拟),我能够生成访问令牌,然后在传递它的同时调用 API,但它 returns 返回
StatusCode: 203, ReasonPhrase: 'Non-Authoritative Information', Version: 1.1, Content:
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;
}
尝试使用邮递员使用上述代码生成的访问令牌进行测试,并获得如下截图。
我在这里做错了什么,我该如何解决这个问题?
azure 广告访问令牌是不记名令牌。您不需要将其用作基本身份验证。
尝试使用以下代码:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", GetYourTokenWithClientCredentialsFlow().Result);
更新:
注册一个新应用
默认将应用设置为 public 客户端
添加 DevOps 权限 API
新建项目,安装Microsoft.IdentityModel.Clients.ActiveDirectory包
代码示例
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();
}
}
}