从 Office 365 返回的 OAuth2 令牌不包含 preffered_username 声明

OAuth2 token returned from Office 365 doesn't contain a preffered_username claim

我按照 this tutorial 进行了解码,并提取了电子邮件地址(应该存储在 preferred_username属性),即如下代码:

decoded_token = Base64.urlsafe_decode64(encoded_token)
jwt = JSON.parse(decoded_token)
email = jwt['preferred_username']

问题是返回的对象不包含这个属性,我得到的类似下面:

{  
   "ver":"2.0",
   "iss":"https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0",
   "aud":"0ab6433e-84fc-469b-8c72-41f7a0241a61",
   "exp":1458142389,
   "iat":1458055989,
   "at_hash":"0OYaLKpTTdHNBrQNOqwQ0Q",
   "sub":"AAAAAAAAAAAAAAAAAAAAAC1TrOaOmvInYrFAyrQjlFI",
   "tid":"9188040d-6c67-4c5b-b112-36a304b66dad"
}

快速浏览 the spec 表明我正在从 Office 365 取回正确的对象,因为 preferred_username 被提及为潜在的声明,但是它不在我取回的对象中。

可能我没有使用正确的参数调用 get_token 函数,但是 the documentation for the library is pretty sparse,所以我真的不能说。

I have raised an issue on Github.

这是Office 365端的错误,教程的错误,还是我自己做错了?

我尝试使用普通 HTTP 请求重现此问题,但我可以成功获得 preferred_username 属性。

据我所知,只有当我们在请求中指定openid范围时,我们才能得到这个属性。为了缩小这个问题的范围,我建议您尝试在没有 Ruby.

的情况下使用 Fiddler 或 Postman

下面是使用浏览器和Fiddler获取id token的测试,供大家参考:

  1. 使用Office 365账号在门户中注册应用(可参考教程)
  2. 通过下面的 link 在网络浏览器中获取授权码: https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={ClientID}&response_type=code&redirect_uri={RedirectURL}&response_mode=query&scope=https%3A%2F%2Foutlook.office.com%2Fmail.read%20https%3A%2F%2Foutlook.office.com%2Fmail.send%20openid&state=12345
  3. 替换预览请求中的授权码并使用 Fiddler 来 post 获取令牌的请求:

    POST: https://login.microsoftonline.com/common/oauth2/v2.0/token grant_type=authorization_code&client_id={ClientID}&scope=https%3A%2F%2Foutlook.office.com%2Fmail.read%20https%3A%2F%2Foutlook.office.com%2Fmail.send%20openid&redirect_uri=http%3A%2F%2Flocalhost%3A55065%2F&client_secret={ClientSecret}&code= {授权码}

  4. 从下面的link解码ID令牌:

    https://jwt.io/

然后我就可以从ID令牌中成功获取preferred_username 属性了。

Microsoft 的 Jason Johnston(本教程的作者)回答 here

The Azure team deployed a breaking change to their v2 auth endpoint, which is causing the preferred_username to not be present. You need to add profile to the SCOPES array in auth_helper.rb. I'll post an update to the tutorial after the Build conference.

auth_helper.rb 中的 SCOPES 数组现在看起来像这样:

SCOPES = [ 'openid', 'https://outlook.office.com/mail.read', 'profile' ]