继上一个问题Group claims with Azure AD and OAuth2 implicit grant in ADAL JS之后,我已经设置了一些内容,以便用户可以使用Azure / ADAL JS进行身份验证,然后我使用他们的令牌代表Azure Graph API访问那个用户。这很有效,我可以获取用户和组信息。
但是,我们现在有一个用例,其他系统将在应用程序的上下文中而不是作为单个用户登录我们的应用程序。我不知道我是否正确地执行了此操作但是我已经获得了第二个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中(让我们称之为我们的AAD应用程序以避免混淆)。这是一个多租户AAD应用程序,用户通过AAD使用OAuth2进行身份验证。
作为企业应用程序,我们的客户都拥有自己的Azure AD(可能会也可能不会同步到内部部署AD)(让我们称之为他们的AAD )。在配置他们的系统以使用我们的应用程序时,我们有一个来自他们的AAD 的全局管理员授予我们的AAD应用程序同意Windows的以下权限Azure Active Directory(使用管理员同意授权):
当用户浏览我们的应用程序时,他们将被重定向到Azure进行身份验证。经过身份验证后(无论是通过他们的AAD 还是通过连接到他们的AAD 的内部部署AD),通过Web应用程序进行的任何API调用都将包含一个Bearer令牌。我们第一次看到每个Bearer令牌时,我们使用它来获取Azure Graph API的新令牌(代表用户)并查询Graph API以获取用户详细信息和组成员身份。当用户使用自己的用户帐户通过UI进行身份验证时,这一切都有效。
我们现在要做的是允许我们的客户让另一个下游应用程序(他们的下游应用程序)获得自己的承载令牌以使用我们的应用程序。这次没有用户,所以我们正在查看client credentials grant flow。为此,我们的客户现在拥有自己的AAD应用程序(他们的AAD应用程序),该应用程序位于他们的AAD (已经获得上述同意)。 他们的下游应用程序可以获得承载令牌来访问我们的应用程序。但是,当我们尝试获取Azure Graph API的令牌(代表他们的下游应用程序)时,它会失败并显示我上面粘贴的错误消息。
我团队的另一名成员已做过一些调查,这些都是他的调查结果。
我已经通过查看SDK在幕后执行的操作手动完成了整个过程 并手动执行所有请求,以便更好地重现我们正在做的事情。
所以调用服务(Azure Active Directory中的Web应用程序设置) 从Azure获取OAuth令牌,即
POST https://login.microsoftonline.com/<tenant-id>/oauth2/token grant_type client_credentials client_id (the client ID of the calling service application in the AD) client secret (the key configured in the calling service application in the AD) resource (the client ID of our web service)
我们获得的有效令牌包含
appid
,tid
,oid
,iss
等,但没有name
,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 (our web service application client ID) client_secret (our web service application client key) resource https://graph.windows.net assertion (the token that was sent by the calling client service, obtained by the process above) requested_token_use on_behalf_of scope 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;
它返回的全部是:
{ "error": "invalid_grant", "error_description": "AADSTS50034: To sign into this application the account must be added to the <customer tenant id> directory.\r\nTrace ID: <removed>\r\nCorrelation ID: <removed>\r\nTimestamp: 2015-10-08 06:37:58Z", "error_codes": [ 50034 ], "timestamp": "2015-10-08 06:37:58Z", "trace_id": "<removed>", "correlation_id": "<removed>" }
所以我想问题是,我们是否可以代表带有持票人令牌的来电者获得图表API令牌, 如果调用者是Web /本机应用程序而不是实际用户?
答案 0 :(得分:1)
有一种方法可以在没有用户凭据的情况下登录Microsoft Graph API。您可以使用card.io
和ClientCredential
设置Client ID
。使用Client Secret
,您可以对ClientCredential
进行身份验证并检索访问令牌。通过访问令牌,您可以访问Graph API。
代码示例:
AuthenticationContext
希望这有帮助!