【发布时间】:2016-05-13 11:10:24
【问题描述】:
我的公司正在研究有关 Azure 的报告。我们只希望我们的客户向我们提供只读凭据以供我们使用。我做了一些研究,看起来 Azure Active Directory 就是这样做的。所以我希望使用只读的 Azure 目录应用程序进行身份验证。
为了让我开始,我关注了这篇关于通过 Azure Active Directory 使用管理 API 的博客。
https://msdn.microsoft.com/en-us/library/azure/dn722415.aspx
除了方法秀很不友好之外,它不起作用=(
以全局管理员身份登录后出现此错误:
“AADSTS90014:请求正文必须包含以下参数:'client_secret or client_assertion'。”
做了一些研究,发现这种身份验证方式适用于本机应用程序,而不是 Web 应用程序(尽管博客文章中说的是其他明智的......)。所以我做了一个调整。我的 GetAuthorizationHeader 现在看起来像这样:
private static string GetAuthorizationHeader()
{
AuthenticationResult result = null;
var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]);
string clientId = ConfigurationManager.AppSettings["clientId"];
string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
var thread = new Thread(() =>
{
result = context.AcquireToken(
"https://management.core.windows.net/",
clientCred);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Name = "AquireTokenThread";
thread.Start();
thread.Join();
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
return token;
}
我能够获得访问令牌(耶)。但是现在当我尝试将它与 Azure 管理库客户端一起使用时,我收到了这个错误:
“ForbiddenError: 服务器未能验证请求。验证证书是否有效并与此订阅相关联。”
我在我的应用程序中仔细检查了我的权限。看起来不错。我尝试授予对所有内容的完全访问权限,看看这是否会有所作为。
我仔细检查了我的tenantId、clientId 和subscriptionId,看起来都不错。
我确保我正在使用的订阅指向我的应用程序所在的 AD。
我尝试制作一个新的密钥。
我猜这是问题所在: 但是在此 UI 中,我无法为该属性选择任何值。我不确定这是错误还是未完成功能的结果。 我在这里遗漏了什么吗?
谢谢
这是我的完整代码供参考:
class Program
{
static void Main(string[] args)
{
var token = GetAuthorizationHeader();
var credential = new TokenCloudCredentials(ConfigurationManager.AppSettings["subscriptionId"], token);
using (var computeClient = new ComputeManagementClient(credential))
{
var images = computeClient.VirtualMachineOSImages.List();
}
}
private static string GetAuthorizationHeader()
{
AuthenticationResult result = null;
var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]);
string clientId = ConfigurationManager.AppSettings["clientId"];
string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
var thread = new Thread(() =>
{
result = context.AcquireToken(
"https://management.core.windows.net/",
clientCred);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Name = "AquireTokenThread";
thread.Start();
thread.Join();
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
return token;
}
}
编辑: 已经取得了进展。正如我与 Gaurav 讨论的那样,我需要放弃 Azure 管理库,因为目前它似乎不支持 Azure 资源管理器 (ARM) API!所以我做了原始的网络请求。它按预期工作。如果我从我的 AD 应用程序中删除角色访问权限,我会被拒绝访问。当我拥有它时,我会取回数据。
我不确定的一件事是让我的应用程序自动添加到新资源中。
另外,有没有办法列出我的 AD 应用程序可以访问的资源组?
新代码:
class Program
{
static void Main(string[] args)
{
var token = GetAuthorizationHeader();
string subscriptionId = ConfigurationManager.AppSettings["subscriptionId"];
string resourceGroupName = ConfigurationManager.AppSettings["resourceGroupName"];
var uriListMachines = string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/virtualmachines?api-version=2015-05-01-preview", subscriptionId, resourceGroupName);
var t = WebRequest.Create(uriListMachines);
t.ContentType = "application/json";
t.Headers.Add("Authorization", "Bearer " + token);
var response = (HttpWebResponse)t.GetResponse();
string result = "";
using (var reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
}
//Original Attempt:
//var credential = new TokenCloudCredentials(ConfigurationManager.AppSettings["subscriptionId"], token);
//using (var client = CloudContext.Clients.CreateComputeManagementClient(credential))
//{
// var images = client.VirtualMachineVMImages.List();
//}
}
private static string GetAuthorizationHeader()
{
AuthenticationResult result = null;
var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]);
string clientId = ConfigurationManager.AppSettings["clientId"];
string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
var thread = new Thread(() =>
{
result = context.AcquireToken(
"https://management.core.windows.net/",
clientCred);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Name = "AquireTokenThread";
thread.Start();
thread.Join();
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
return token;
}
}
编辑编辑: 我发现我挂了。在 OLD 门户中创建的资源将拥有自己独特的资源组。
据我所知,您无法添加在旧门户现有资源组中制作的资源 (boooo)。在新门户中创建的资源将能够将资源分配给现有组(也就是授予对我的 AD 应用程序的角色访问权限的组)。
这真是一团糟!但至少我知道现在发生了什么。
【问题讨论】:
标签: c# azure authentication azure-active-directory azure-sdk-.net