继我之前的问题:Group claims with Azure AD and OAuth2 implicit grant in ADAL JS,我've have things set up so users can authenticate using Azure/ADAL JS and then I use the their token to access the Azure Graph API on behalf of that user. This works well and I'能够获得他们的用户和组信息 .
但是,我们现在有一个用例,其他系统将在应用程序中登录我们的应用程序's context rather than as an individual user. I don'知道我是否已获得第二个Azure AD应用程序,其客户端密钥由requesting a token from the AAD API进行身份验证 . 我可以获得一个令牌并将其传递给我们的应用程序 . 但是,我不能再使用该令牌代表该用户(现在是一个应用程序)访问Azure Graph API .
首先,这实际上是可能做的还是我尝试不可能的?
如果可能的话,我必须做些什么才能让它发挥作用?它只是Azure应用程序中的权限还是我需要在代码中以不同方式执行?
我用来代表用户访问Graph API的代码(删除了异常处理和空检查)是:
var authContext = new AuthenticationContext("https://login.microsoftonline.com/common");
var clientCredential = new ClientCredential("clientId", "key");
var userAssertion = new UserAssertion(((BootstrapContext)identity.BootstrapContext).Token);
var result = await authContext.AcquireTokenAsync("https://graph.windows.net", clientCredential, userAssertion);
return result.AccessToken;
我得到的例外是 AADSTS50034: To sign into this application the account must be added to the {directory ID of my main application} directory
,错误为 invalid_grant
.
我似乎无法弄清楚我做错了什么,因为我相信所有Azure应用程序都配置正确,至少它们是用于用户身份验证 . 我还将相同的应用程序和委派权限应用于我的第二个Azure AD(客户端)应用程序,其他目录需要用户身份验证 .
任何帮助,将不胜感激 .
更新:系统概述/配置
所以我似乎没有提供足够的关于系统配置的上下文,所以让我试着在这里解决这个问题 .
我们有一个在Azure中运行的企业SaaS应用程序(我们称之为我们的应用程序) . 它在Azure AD中有一个"application"(让我们称之为我们的AAD应用程序以避免混淆) . 这是一个多租户AAD应用程序,用户通过AAD使用OAuth2进行身份验证 .
作为企业应用程序,我们的客户都拥有自己的Azure AD(可能会也可能不会同步到内部部署AD)(让我们将其称为AAD) . 在配置他们的系统以使用我们的应用程序时,我们有一个来自他们的AAD授权的全局管理员我们的AAD应用程序同意Windows Azure Active Directory的以下权限(使用管理员同意授权):
-
应用程序权限:
-
读取目录数据
-
委托权限:
-
以登录用户身份访问目录
-
读取目录数据
-
登录并阅读用户 Profiles
当用户浏览到我们的应用程序时,他们将被重定向到Azure进行身份验证 . 经过身份验证(无论是通过其AAD还是通过连接到其AAD的内部部署AD),通过Web应用程序进行的任何API调用都将包含Bearer令牌 . 我们第一次看到每个Bearer令牌时,我们使用它来获取Azure Graph API的新令牌(代表用户)并查询Graph API以获取用户详细信息和组成员身份 . 当用户使用自己的用户帐户通过UI进行身份验证时,这一切都有效 .
我们现在要做的是允许我们的客户让另一个下游应用程序(他们的下游应用程序)获得自己的Bearer令牌来使用我们的应用程序 . 这次没有用户,所以我们正在查看client credentials grant flow . 为此,我们的客户现在拥有自己的AAD应用程序(他们的AAD应用程序),这些应用程序位于他们的AAD中(已经获得了上述同意) . 他们的下游应用程序可以获得Bearer令牌来访问我们的应用程序 . 但是,当我们尝试获取Azure Graph API(代表其下游应用程序)的令牌时,它会失败并显示我上面粘贴的错误消息 .
更新2
我团队的另一名成员做了一些调查,这些都是他的发现 .
我通过查看SDK在幕后执行的操作并手动执行所有请求来手动完成此过程,以便更好地重现我们正在做的事情 . 因此,调用服务(Azure Active Directory中的Web应用程序设置)从Azure获取OAuth令牌,即POST https://login.microsoftonline.com/<tenant-id>/oauth2/token
grant_type client_credentials
client_id(AD中呼叫服务应用程序的客户端ID)
客户端密钥(在AD中的呼叫服务应用程序中配置的密钥)
资源(我们的Web服务的客户端ID)
我们得到一个有效的令牌,其中包含appid,tid,oid,iss等,但没有名称,upn等等(因为它不是用户而是应用程序) . 那么我们想要从Graph API中查找服务主体的详细信息,并且我们要求代表应用程序获取Graph API令牌,即POST https://login.microsoftonline.com/common/oauth2/token
grant_type urn:ietf:params:oauth:grant-type:jwt-bearer
client_id(我们的Web服务应用程序客户端ID)
client_secret(我们的Web服务应用程序客户端密钥)
资源https://graph.windows.net
断言(由调用客户端服务发送的令牌,由上面的过程获得)
requested_token_use代表
范围openid
这基本上是当我们调用以下代码(从SDK代码中提取)时发生的事情var authContext = new AuthenticationContext(“https://login.microsoftonline.com/common”);
var clientCredential = new ClientCredential(“clientId”,“key”);
var userAssertion = new UserAssertion(((BootstrapContext)identity.BootstrapContext).Token);
var result = await authContext.AcquireTokenAsync(“https://graph.windows.net”,clientCredential,userAssertion);
return result.AccessToken;
它返回的全部是:{
“错误”:“invalid_grant”,
“error_description”:“AADSTS50034:要登录此应用程序,必须将帐户添加到<客户租户ID>目录 . \ r \ nTrace ID:<已删除> \ r \ n相关ID:<已删除> \ r \ n时间戳:2015 -10-08 06:37:58Z“,
“error_codes”:[50034],
“timestamp”:“2015-10-08 06:37:58Z”,
“trace_id”:“<删除>”,
“correlation_id”:“<删除>”
}
所以我想问题是,如果调用者是Web /本机应用程序而不是实际用户,我们是否可以代表具有承载令牌的调用者获得图形API令牌?
1 回答
有一种方法可以在没有用户凭据的情况下登录Microsoft Graph API . 您可以使用
Client ID
和Client Secret
设置ClientCredential
. 使用ClientCredential
,您可以验证AuthenticationContext
并检索访问令牌 . 通过访问令牌,您可以访问Graph API .Code Sample:
希望这可以帮助!