Azure AD:"范围"访问令牌响应正文中遗漏的属性

时间:2016-12-28 21:09:12

标签: python azure office365 microsoft-graph

我正在编写一个Python脚本来编辑存在于SharePoint中的Excel电子表格。我们有Office 365 for Business。我正在使用Microsoft Graph API。 我使用Microsoft Azure Active Directory(AD)注册了Python应用程序,并为Graph API添加了以下2个(仅限应用程序)权限:(1)在所有网站集中读取和写入文件(预览)和(2)读取目录数据。 (我让公司管理员为我注册了应用程序。)

我的Python脚本使用请求库发送REST请求:

import json
import requests

MSGRAPH_URI = 'https://graph.microsoft.com'
VERSION = 'v1.0'

def requestAccessToken(tenant_id, app_id, app_key):
    MSLOGIN_URI = 'https://login.microsoftonline.com'
    ACCESS_TOKEN_PATH = 'oauth2/token'
    GRANT_TYPE = 'client_credentials'
    endpoint = '{0}/{1}/{2}'.format(MSLOGIN_URI, tenant_id, ACCESS_TOKEN_PATH)
    headers = {'Content-Type': 'Application/Json'}
    data = {
        'grant_type': GRANT_TYPE,
        'client_id': app_id,
        'client_secret': app_key,
        'resource': MSGRAPH_URI

    }
    access_token = response.json()['access_token']
    return access_token

def getWorkbookID(access_token, fileName):
    endpoint = '{0}/{1}/me/drive/root/children'.format(MSGRAPH_URI, VERSION)
    headers = {
        'Content-Type': 'Application/Json',
        'Authorization': 'Bearer {}'.format(access_token)
    }
    response = requests.get(endpoint, headers=headers)
    print response.text
    assert response.status_code == 200
    items = response.json()['value']
    workbook_id = None
    for item in items:
        if item['name'] == fileName:
            workbook_id = item['id']
    return workbook_id

access_token = requestAccessToken(TENANT_ID, APP_ID, APP_KEY)
workbook_id = getWorkbookID(access_token, WORKBOOK_FILENAME)

Python应用程序成功地从Microsoft服务器请求并接收access_token。访问令牌就像这样开始

eyJ0eXAiOiJKV1QiLCJub25jZSI6...

然后它在getWorkbookID()中请求我的文件列表:

GET https://graph.microsoft.com/v1.0/me/drive/root/children
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6...

这是对该REST请求的响应:

{
  "error": {
    "code": "InternalServerError",
    "message": "Object reference not set to an instance of an object.",
    "innerError": {
      "request-id": "aa97a822-7ac5-4986-8ac0-9852146e149a",
      "date": "2016-12-26T22:13:54"
    }
  }
}

请注意,当我通过Graph Explorer(https://graph.microsoft.io/en-us/graph-explorer)请求时,我成功获取了我的文件列表。

编辑:

  1. 更改标题来自" Microsoft Graph API返回对象引用未设置为对象的实例"到" Azure AD"范围"缺少访问令牌响应"。
  2. 更改了" me"在阅读此内容之后,在GET请求的uri中,我的组织" myOrganization":graph.microsft.io/en-us/docs/overview/call_api
  3. 即,

    GET https://graph.microsoft.com/v1.0/myOrganization/drive/root/children
    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6...
    

    现在得到以下回复。

    {
      "error": {
        "code": "AccessDenied",
        "message": "Either scp or roles claim need to be present in the token.",
        "innerError": {
          "request-id": "bddb8c51-535f-456b-b43e-5cfdf32bd8a5",
          "date": "2016-12-28T22:39:25"
        }
      }
    }
    

    查看graph.microsoft.io/en-us/docs/authorization/app_authorization中的示例,我看到访问令牌响应正文包含"范围"列出在应用程序注册期间为应用授予的权限的属性。但是,我从服务器收到的访问令牌响应没有"范围"属性。这是我的访问令牌响应的样子。

    {
    "token_type":"Bearer",
    "expires_in":"3599",
    "ext_expires_in":"0",
    "expires_on":"1482968367",
    "not_before":"1482964467",
    "resource":"https://graph.microsoft.com",
    "access_token":"eyJ0eXAiOiJKV..."
    }
    

    问题:

    1. 我让管理员在Azure AD中注册了应用程序,并选中所需的Microsoft Graph API应用程序权限框。显然这还不够。还需要什么?为什么权限不在访问令牌响应主体中?
    2. GET请求的正确URI是什么?是" MyOrganization" URI中的正确值?

3 个答案:

答案 0 :(得分:1)

感谢大家的回复。经过更多的研究,我找到了问题的答案。

原始问题:“Microsoft Graph API返回未将对象引用设置为对象实例”

请求

GET https://graph.microsoft.com/v1.0/me/drive/root/children
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6...

获得回复

{
  "error": {
    "code": "InternalServerError",
    "message": "Object reference not set to an instance of an object.",
    "innerError": {
      "request-id": "aa97a822-7ac5-4986-8ac0-9852146e149a",
      "date": "2016-12-26T22:13:54"
    }
  }
}

正如@ SriramDhanasekaran-MSFT所指出的那样,/me指的是当前登录的用户。在我们的示例中,我们没有登录用户,因此我们无法使用/me。相反,我们可以使用/myOrganization或不使用任何内容,它是可选的。

更新的问题:“Azure AD”范围“访问令牌响应中缺少的属性”

更新(替换/ me with / myOrganization)请求

GET https://graph.microsoft.com/v1.0/myOrganization/drive/root/children
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6...

获得回复

{
  "error": {
    "code": "AccessDenied",
    "message": "Either scp or roles claim need to be present in the token.",
    "innerError": {
      "request-id": "bddb8c51-535f-456b-b43e-5cfdf32bd8a5",
      "date": "2016-12-28T22:39:25"
    }
  }
}

正如@ SriramDhanasekaran-MSFT和@ DanKershaw-MSFT所提到的,access_token响应缺少scope属性的原因是管理员未在Azure AD中“授予”权限

然而,@ SriramDhanasekaran-MSFT提供的解决方案:

https://login.microsoftonline.com/common/oauth2/authorize?client_id=&response_type=code&redirect_uri=http://localhost&resource=https://graph.microsoft.com&prompt=consent

对我没用,因为我的应用没有redirect uri。授予权限的解决方案比这简单:只需让管理员登录到Azure AD并单击“授予权限”链接以授予权限。

此外,/myOrganization/driver/root/children列出了管理员驱动器的内容。正如@PeterPan-MSFT所指出的,要列出其他用户的驱动器,请将/myOrganization替换为/users/<user-id>

成功:

我的应用程序现在可以在线编辑我的Excel电子表格,而无需人工用户的干预。与@ PeterPan-MSFT所说的相反,使用Graph API可以实现这一点,无需下载Excel电子表格并离线编辑。

要点:

存在两个问题:(1)使用/me和(2)管理员尚未在Azure AD中授予应用程序权限。

答案 1 :(得分:0)

由于正在使用client_credential令牌流(即,没有经过身份验证的用户上下文),因此/ me的任何请求都无效,因为/ me指的是当前已登录的用户。如果您要访问用户驱动器中的文件,请尝试使用委派令牌。

要在Sharepoint中访问root驱动器,请求url是/ drive / root / children(myorganization是可选的)。

关于遗漏索赔,管理员必须同意该应用程序。您可以通过要求管理员访问以下网址(替换为您应用的网址)来强制同意

https://login.microsoftonline.com/common/oauth2/authorize?client_id=&安培; RESPONSE_TYPE =代码&安培; REDIRECT_URI = http://localhost&resource=https://graph.microsoft.com&prompt=consent

答案 2 :(得分:0)

正如@juunas所说,下面的第一个错误信息应该是.NET中的NULL异常,它在服务器端引起,但也不是API错误或权限问题。

setInterval(function(){
    console.log(new Date());
},1000);

您可以参考SO thread了解此案例似乎会针对后端进行更新,请稍后再试。

要解释当您将图谱API网址中的选项error": { "code": "InternalServerError", "message": "Object reference not set to an instance of an object.", 更改为me时的第二个错误,如@ SriramDhanasekaran-MSFT,它会访问当前用户的文件或指定的用户使用myOrganization而不是<user-id>

但是,根据我的理解,您希望编辑SharePoint中的Excel电子表格以进行组织,但似乎不适合使用Graph API。根据我的经验,应该通过使用OneDrive for Business的API将Excel文件复制到本地进行编辑和操作。上传以覆盖它,请参阅the dev documents for OneDrive并尝试使用the API for drive resource

希望它有所帮助。