
[英]CORS error in authenticating .NET Core 2.2 API with Azure Active Directory
[英]Error making Azure Management Library API call when authenticating with azure active directory
我的公司正在研究有关Azure的报告。 我们只希望我们的客户给我们只读的凭证供我们使用。 我做了一些研究,看起来Azure Active Directory就是这样做的。 因此,我正在寻找使用只读Azure目录应用程序进行身份验证的方法。
为了让我开始工作,我关注了此博客,介绍如何通过Azure Active Directory使用Management API。
https://msdn.microsoft.com/zh-CN/library/azure/dn722415.aspx
除了方法显示非常不友好之外,它不起作用=(
以全局管理员身份登录后,出现此错误:
“ AADSTS90014:请求正文必须包含以下参数:'client_secret或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,它们看起来都不错。
我确保我正在使用的订阅指向我的应用程序所在的广告。
我尝试制作新的密钥。
我的猜测是这是问题所在: 但是,在此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! 因此,我做了原始的Web请求。 它按预期工作。 如果我从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应用程序角色访问权限的组)。
真是一团糟! 但是至少我知道现在发生了什么。
我相信您在遇到这个问题的道路上是正确的。
这是正在发生的事情:
本质上,执行Service Management API
的delegated permission and not an application permission
是delegated permission and not an application permission
。 换句话说,在为其获取令牌的用户的上下文中执行API。 现在,您正在为您的应用程序获取此令牌(由客户端ID /秘密指定)。 但是,您的应用程序无权访问Azure订阅,因为在Azure AD中为此应用程序创建的用户记录属于Service Principal
类型。 由于此服务主体无权访问您的Azure订阅,因此您会收到此“ Forbidden Error
(我必须说该错误具有误导性,因为您根本没有使用证书)。
您可以做一些事情:
Azure Portal
将其分配给特定角色。 请参阅此链接以获取有关此内容的更多详细信息: https : //azure.microsoft.com/zh-cn/documentation/articles/resource-group-create-service-principal-portal/ 。 Co-Admin
,并且将拥有对您的Azure订阅的完全访问权限,因为使用SM API时,没有Role-based access control
概念。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.