我正在编写一个简单的桌面应用程序,需要从Microsoft的目录中检索有关用户的一些基本属性。具体做法是:
到目前为止,我已完成以下工作: -
Azure AD Graph API似乎是获取配置文件信息的正确方法。特别是,该信息可在端点获得:https://graph.windows.net/ {tenant} / users / {email}?api-version = 1.6
在AAD中注册本机应用程序时,未提供任何密钥。所以我没有客户的秘密。
在这里查看GitHub中的示例:https://github.com/Azure-Samples/active-directory-dotnet-graphapi-console。这里的说明似乎是错误的,因为没有Keys部分可用[见(2)]。
基于上面的示例,我写了一个简单的函数。代码如下:
private static async Task PrintAADUserData(string email)
{
string clientId = "0a202b2c-6220-438d-9501-036d4e05037f";
Uri redirectUri = new Uri("http://localhost:4000");
string resource = "https://graph.windows.net/{tenant}";
string authority = "https://login.microsoftonline.com/{tenant}/oauth2/authorize";
AuthenticationContext authContext = new AuthenticationContext(authority);
AuthenticationResult authResult = await authContext.AcquireTokenAsync(resource, clientId, redirectUri, new PlatformParameters(PromptBehavior.Auto));
string api = String.Format("https://graph.windows.net/{tenant}/users/{0}?api-version=1.6", email);
LOG.DebugFormat("Using API URL {0}", api);
// Create an HTTP client and add the token to the Authorization header
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authResult.AccessTokenType, authResult.AccessToken);
HttpResponseMessage response = await httpClient.GetAsync(api);
string data = await response.Content.ReadAsStringAsync();
LOG.Debug(data);
}
问题
运行时的应用程序能够启动身份验证页面。我为什么需要那个?该应用程序已作为我的域帐户运行。是否需要额外的身份验证?如果我在Azure中将此应用程序作为工作进程运行,那么我就不想使用我的域凭据。
主要问题似乎是资源网址错误。访问Azure AD Graph API需要指定哪些资源?
谢谢,
Vijai。
EDITS
根据@Saca的评论,代码和应用程序已经过编辑。
代码
string clientId = ConfigurationManager.AppSettings["AADClientId"];
string clientSecret = ConfigurationManager.AppSettings["AADClientSecret"];
string appIdUri = ConfigurationManager.AppSettings["AADAppIdURI"];
string authEndpoint = ConfigurationManager.AppSettings["AADGraphAuthority"];
string graphEndpoint = ConfigurationManager.AppSettings["AADGraphEndpoint"];
AuthenticationContext authContext = new AuthenticationContext(authEndpoint, false);
AuthenticationResult authResult = await authContext.AcquireTokenAsync("https://graph.windows.net", new ClientCredential(clientId, clientSecret));
ExistingTokenWrapper wrapper = new ExistingTokenWrapper(authResult.AccessToken);
ActiveDirectoryClient client = new ActiveDirectoryClient(new Uri(graphEndpoint), async () => await wrapper.GetToken());
IUser user = client.Users.Where(_ => _.UserPrincipalName.Equals(email.ToLowerInvariant())).Take(1).ExecuteSingleAsync().Result;
应用 的 错误 未处理的异常:System.AggregateException:发生一个或多个错误。 ---> System.AggregateException:发生一个或多个错误。 ---> Microsoft.Data.OData.ODataErrorException:没有足够的权限来完成操作。 ---> System.Data.Services.Client.DataServiceQueryException:处理此请求时发生错误。 ---> System.Data.Services.Client.DataServiceClientException:{" odata.error":{" code":" Authorization_RequestDenied"," message": {" lang":" zh","价值":"没有足够的权限来完成操作。"}}}
看来,尽管提供了正确的权限,正确的资源并且能够获取令牌,但仍然存在缺失。
答案 0 :(得分:1)
此处需要考虑的关键是,如果您的应用程序是无人机客户端,则由用户在其计算机上运行的安全服务器或桌面客户端运行。
如果是前者,则您的应用程序被视为机密客户端,并且可以信任秘密,即密钥。如果这是您的方案,即样本所涵盖的方案,那么您需要使用clientId和clientSecret。
您在应用程序的配置页面中没有看到 Keys 部分的最可能原因是,而不是选择 Web应用程序和/或Web API ,根据示例中的步骤#7,您在首次创建应用程序时选择了 Native Client Application 。此“类型”无法更改,因此您需要创建一个新的应用程序。
如果您的方案是后者,那么您的应用程序将被视为公共客户端,并且不能信任秘密,在这种情况下,您唯一的选择是提示用户输入凭据。否则,即使您的应用程序拥有自己的授权层,也可以轻松反编译并提取和使用秘密。
顺便说一句,您的资源网址是正确的。
答案 1 :(得分:0)
原来问题不在于代码。我不是AAD管理员。似乎任何需要在我们的租户中对AAD执行身份验证的应用程序都需要具有AAD管理员启用的权限。一旦他们为我的应用程序启用了权限(并获得了AAD注册的所有权),这就开始工作了。
答案 2 :(得分:0)
希望帮助一些使用GraphClient的人:
var userPriNam = "johndoe@cloudalloc.com";
var userLookupTask = activeDirectoryClient.Users.Where(
user => user.UserPrincipalName.Equals(userPriNam, StringComparison.CurrentCultureIgnoreCase)).ExecuteSingleAsync();
User userJohnDoe = (User)await userLookupTask;
来自https://www.simple-talk.com/cloud/security-and-compliance/azure-active-directory-part-5-graph-api/