Microsoft图形返回“访问令牌为空”

时间:2018-08-14 15:49:15

标签: azure-active-directory microsoft-graph

我发布了此请求:

 
POST https://login.microsoftonline.com:443/{my-tennant-here}/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com 
Content-Type: application/x-www-form-urlencoded

client_id={client id here}
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret={client secret here}
&grant_type=client_credentials
 

这将返回:

 
{
  "token_type": "Bearer",
  "expires_in": 3599,
  "ext_expires_in": 0,
  "access_token": "eyJ0eX......
}
 

我已经使用jwt.io解码了令牌,它肯定不是空的。它包含14个声明。 aud,iss,tid等...

然后我在此请求中使用访问令牌

 
GET https://graph.microsoft.com/v1.0/users
Athorization: Bearer eyJ0eX...
 

然后我得到这个机构的401未经授权:

 
{
  "error": {
    "code": "InvalidAuthenticationToken",
    "message": "Access token is empty.",
    "innerError": {
      "request-id": "",
      "date": "2018-08-14T15:41:44"
    }
  }
}
 

预期结果为200 Ok,其中包含用户列表的正文

这是否仅表示我的应用程序未经授权,并且错误消息只是误导性(访问令牌为空)? 还是我做错了什么?

更新: 我注意到,尽管令牌确实包含声明,但它没有范围声明,这对我来说似乎有点奇怪。我假设它具有User.Read.All范围。该应用程序(客户端ID /客户端密码)应具有此权限。 我收到的令牌中的声明具有以下声明:

 
aud: "https://graph.microsoft.com",
iss: "https://sts.windows.net/my tennant id",
iat: timestamp
nbf: timestamp
exp: timestamp
aio: looks like some kind of signature
app_displayname: "the expected app name"
appid: "the expected appid"
appidacr: "1"
idp: "https://sts.windows.net/...."
oid: "GUID"
sub: "GUID"
tid: "my tennant id"
uti: "value"
ver: 1.0 

5 个答案:

答案 0 :(得分:1)

一个网址有效,而另一个网址无效。

这有效:

endpoint = "https://graph.microsoft.com/v1.0/reports/getOffice365ActiveUserDetail%28period%3D%27D7%27%29"
headers = {"Authorization": 'Bearer ' + access_token_gmc}
response = requests.get(endpoint, headers=headers)

但这不是:

endpoint = "https://graph.microsoft.com/v1.0//users/myuserid/calendars"
headers = {"Authorization": 'Bearer ' + access_token_gmc}
response = requests.get(endpoint, headers=headers)  

请确保拼写正确。

答案 1 :(得分:0)

授权标头拼写错误。

因此,“访问令牌为空”实际上可能意味着不存在,甚至“请求中没有授权标头”。

答案 2 :(得分:0)

对于User.Read.All范围,您不能征得用户的同意。必须经过管理员同意。看来您可能错过了使用管理员帐户同意您的应用的权限。

要执行以下操作:

GET https://login.microsoftonline.com/{tenant}/adminconsent
?client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&state=12345
&redirect_uri=http://localhost/myapp/permissions

然后获取访问令牌,您应该获取管理员已同意用户的范围。

答案 3 :(得分:0)

对我来说,我的问题是我在请求url和Authorization标头之间放置了一个换行符,使之成为正文。

错误:

GET https://graph.microsoft.com/v1.0/users

Authorization: Bearer {{token}}

正确:

GET https://graph.microsoft.com/v1.0/users
Authorization: Bearer {{token}}

一个愚蠢的错误,但很容易忽略-如果您读到这篇文章,您可能犯了一个愚蠢的错误,例如OP(错字)或此类错误。再次浏览您的请求语法!

答案 4 :(得分:0)

我在使用angular的{​​{1}}应用程序中遇到相同的错误。

enter image description here

这完全是由于MSAL中提供的API scope错误。我之前有MSALAngularConfigFactory

environment

您可以看到我在export const environment = { production: false, clientId: 'clientid', redirectUrl: 'http://localhost:4200', graphApiUrl: 'https://graph.microsoft.com/v1.0', graphGetUserImage: '/me/photo/$value', protectedResourceMap: [ ['http://localhost:65498/api', ['api.access']], ['https://graph.microsoft.com/beta', ['user.read']] ] as [string, string[]][], authority: 'https://login.microsoftonline.com/organizations' }; 中给出了https://graph.microsoft.com/beta,这是错误的。相反,我们应该给protectedResourceMap。所以这里是正确的https://graph.microsoft.com/v1.0/

environment

我在export const environment = { production: false, clientId: 'clientid', redirectUrl: 'http://localhost:4200', graphApiUrl: 'https://graph.microsoft.com/v1.0', graphGetUserImage: '/me/photo/$value', protectedResourceMap: [ ['http://localhost:65498/api', ['api.access']], ['https://graph.microsoft.com/v1.0/', ['user.read']] ] as [string, string[]][], authority: 'https://login.microsoftonline.com/organizations' }; 中使用它,如下所示。

app.module.ts