Azure AD:"scope" 属性 访问令牌响应中缺少 Body
Azure AD: "scope" Property Missing from Access Token Response Body
我正在编写 Python 脚本来编辑 SharePoint 中的 Excel 电子表格。我们有 Office 365 商业版。我正在使用 Microsoft Graph API。
我在 Microsoft Azure Active Directory (AD) 中注册了 Python 应用程序,并为 Graph API 添加了以下 2 (app-only) 权限:(1) 在所有站点中读取和写入文件 collections(预览)和(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) 请求时,我成功获得了我的文件列表。
编辑:
- 已将标题从 "Microsoft Graph API Returns Object reference not set to an instance of an object" 更改为 "Azure AD "范围“访问令牌响应中缺少”。
- 将GET请求的uri中的"me"修改为"myOrganization",看完这个:graph.microsft.io/en-us/docs/overview/call_api
即
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 中的示例,我看到访问令牌响应 body 包含列出权限的 "scope" 属性在应用程序注册期间授予该应用程序。但是,我从服务器收到的访问令牌响应没有 "scope" 属性。这是我的访问令牌响应的样子。
{
"token_type":"Bearer",
"expires_in":"3599",
"ext_expires_in":"0",
"expires_on":"1482968367",
"not_before":"1482964467",
"resource":"https://graph.microsoft.com",
"access_token":"eyJ0eXAiOiJKV..."
}
问题:
- 我让管理员在 Azure AD 中注册了该应用程序,并选中了所需的 Microsoft Graph API 应用程序权限复选框。显然这还不够。还需要什么?为什么权限不在访问令牌响应中 body?
- GET 请求的正确 URI 是什么? "MyOrganization" URI 中的值是否正确?
由于正在使用 client_credential 令牌流(即,没有经过身份验证的用户上下文),任何带有 /me 的请求都是无效的,因为 /me 指的是当前登录的用户。如果您要访问用户驱动器中的文件,请尝试使用委托令牌。
要访问 Sharepoint 中的根驱动器,请求 url 是 /drive/root/children(我的组织是可选的)。
关于丢失的声明,管理员必须同意该应用程序。您可以通过要求管理员访问以下 url(替换为您应用的)
来强制同意
https://login.microsoftonline.com/common/oauth2/authorize?client_id=&response_type=code&redirect_uri=http://localhost&resource=https://graph.microsoft.com&prompt=consent
正如@juunas所说,下面第一个错误信息应该是服务端导致的.NET中的NULL异常,但也不是API错误或权限问题。
error": {
"code": "InternalServerError",
"message": "Object reference not set to an instance of an object.",
你可以参考SO thread知道这个案例好像是后台更新的,请稍后再试。
解释第二个错误,当你在图表 API url 中将选项 me
更改为 myOrganization
时,@SriramDhanasekaran-MSFT,它正在访问文件对于当前用户或指定用户 <user-id>
而不是 me
.
但是,根据我的理解,您想为您的组织编辑 SharePoint 中的 Excel 电子表格,似乎不适合使用 Graph APIs。根据我的经验,应该使用OneDrive for Business的APIs将Excel文件复制到本地进行编辑上传覆盖,请参考the dev documents for OneDrive and try to use the API for drive resource.
希望对您有所帮助。
感谢大家的回复。经过更多研究,我找到了问题的答案。
原题:"Microsoft Graph API Returns Object reference not set to an instance of an object"
要求
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 "scope" 属性 Access Token Response 缺失"
已更新(将 /me 替换为 /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
属性 的原因是权限未被 "granted" 管理员在 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 并单击 "Grant Permissions" link 即可授予权限。
此外,/myOrganization/driver/root/children
列出了管理员驱动器的内容。正如@PeterPan-MSFT 指出的那样,要列出不同用户的驱动器,请将 /myOrganization
替换为 /users/<user-id>
。
成功:
我的应用程序现在可以在线编辑我的 Excel 电子表格,无需人工干预。与@PeterPan-MSFT 所说的相反,这可以通过 Graph API 实现,无需下载 Excel 电子表格并离线编辑。
总结:
有两个问题:(1) 使用 /me
和 (2) 管理员未在 Azure AD 中授予应用程序权限。
我正在编写 Python 脚本来编辑 SharePoint 中的 Excel 电子表格。我们有 Office 365 商业版。我正在使用 Microsoft Graph API。 我在 Microsoft Azure Active Directory (AD) 中注册了 Python 应用程序,并为 Graph API 添加了以下 2 (app-only) 权限:(1) 在所有站点中读取和写入文件 collections(预览)和(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) 请求时,我成功获得了我的文件列表。
编辑:
- 已将标题从 "Microsoft Graph API Returns Object reference not set to an instance of an object" 更改为 "Azure AD "范围“访问令牌响应中缺少”。
- 将GET请求的uri中的"me"修改为"myOrganization",看完这个:graph.microsft.io/en-us/docs/overview/call_api
即
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 中的示例,我看到访问令牌响应 body 包含列出权限的 "scope" 属性在应用程序注册期间授予该应用程序。但是,我从服务器收到的访问令牌响应没有 "scope" 属性。这是我的访问令牌响应的样子。
{
"token_type":"Bearer",
"expires_in":"3599",
"ext_expires_in":"0",
"expires_on":"1482968367",
"not_before":"1482964467",
"resource":"https://graph.microsoft.com",
"access_token":"eyJ0eXAiOiJKV..."
}
问题:
- 我让管理员在 Azure AD 中注册了该应用程序,并选中了所需的 Microsoft Graph API 应用程序权限复选框。显然这还不够。还需要什么?为什么权限不在访问令牌响应中 body?
- GET 请求的正确 URI 是什么? "MyOrganization" URI 中的值是否正确?
由于正在使用 client_credential 令牌流(即,没有经过身份验证的用户上下文),任何带有 /me 的请求都是无效的,因为 /me 指的是当前登录的用户。如果您要访问用户驱动器中的文件,请尝试使用委托令牌。
要访问 Sharepoint 中的根驱动器,请求 url 是 /drive/root/children(我的组织是可选的)。
关于丢失的声明,管理员必须同意该应用程序。您可以通过要求管理员访问以下 url(替换为您应用的)
来强制同意https://login.microsoftonline.com/common/oauth2/authorize?client_id=&response_type=code&redirect_uri=http://localhost&resource=https://graph.microsoft.com&prompt=consent
正如@juunas所说,下面第一个错误信息应该是服务端导致的.NET中的NULL异常,但也不是API错误或权限问题。
error": { "code": "InternalServerError", "message": "Object reference not set to an instance of an object.",
你可以参考SO thread知道这个案例好像是后台更新的,请稍后再试。
解释第二个错误,当你在图表 API url 中将选项 me
更改为 myOrganization
时,@SriramDhanasekaran-MSFT,它正在访问文件对于当前用户或指定用户 <user-id>
而不是 me
.
但是,根据我的理解,您想为您的组织编辑 SharePoint 中的 Excel 电子表格,似乎不适合使用 Graph APIs。根据我的经验,应该使用OneDrive for Business的APIs将Excel文件复制到本地进行编辑上传覆盖,请参考the dev documents for OneDrive and try to use the API for drive resource.
希望对您有所帮助。
感谢大家的回复。经过更多研究,我找到了问题的答案。
原题:"Microsoft Graph API Returns Object reference not set to an instance of an object"
要求
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 "scope" 属性 Access Token Response 缺失"
已更新(将 /me 替换为 /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
属性 的原因是权限未被 "granted" 管理员在 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 并单击 "Grant Permissions" link 即可授予权限。
此外,/myOrganization/driver/root/children
列出了管理员驱动器的内容。正如@PeterPan-MSFT 指出的那样,要列出不同用户的驱动器,请将 /myOrganization
替换为 /users/<user-id>
。
成功:
我的应用程序现在可以在线编辑我的 Excel 电子表格,无需人工干预。与@PeterPan-MSFT 所说的相反,这可以通过 Graph API 实现,无需下载 Excel 电子表格并离线编辑。
总结:
有两个问题:(1) 使用 /me
和 (2) 管理员未在 Azure AD 中授予应用程序权限。