Microsoft Azure AD 图 API:如何检索用户的电子邮件地址?

Microsoft Azure AD graph API: How do I retrieve a user's email address?

我能够访问用户的 accessToken,并且正在使用 Authorization: Bearer <token> header.

调用 GET https://graph.microsoft.com/v1.0/me

但是,在响应中 body 我得到了这样的信息:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users",
    "value": [
        {
            "givenName": "Foo",
            "surname": "Bar",
            "displayName": "Foo Bar",
            "id": "b41efha115adcca29",
            "userPrincipalName": "email.address@outlook.com",
            "businessPhones": [],
            "jobTitle": null,
            "mail": null,
            "mobilePhone": null,
            "officeLocation": null,
            "preferredLanguage": null
        }
    ]
}

mail 属性 是 null,并且此响应 body 中的 userPrincipalName 恰好是用户的电子邮件地址。但是,Microsoft 的 docs:

中有这个

Although the UPN and email share the same format, the value of the UPN for a user might or might not be the same as the email address of the user.

发起用户登录请求时,我们请求 "user.read""email" 范围。我们正在使用 MSAL.js 库来获取访问令牌,我们的代码如下所示:

login (): ng.IPromise<IMicrosoftOAuthResponse> {
  const prom = this.userAgentApplication.loginPopup(["user.read", "email"])
    .then((idToken) => {
      return this.userAgentApplication.acquireTokenSilent(["user.read", "email"]);
    })
    .then((accessToken) => {
      // at this point, we have the accessToken and make a call to the graph api
    });
  return this.$q.when(prom);
}

如何在此处获取用户的实际电子邮件地址?

mail 属性 以两种方式之一设置:

  1. 已在本地 AD 上设置,然后使用 AD Connect 同步到 Azure AD
  2. 已为云用户分配了 Office 365 许可证(和邮箱),此时已为该许可用户设置 mail 属性。

如果用户没有O365 mailbox/license,您还可以通过userPrincipalName、displayName等搜索用户。$filter支持OR运算符。

希望这对您有所帮助,

使用以下 link 在 Microsoft Office 365 商业高级版中创建一个试用帐户: https://signup.microsoft.com/Signup?OfferId=467eab54-127b-42d3-b046-3844b860bebf&dl=O365_BUSINESS_PREMIUM&culture=en-IN&country=IN&ali=1

创建帐户时按照步骤操作。它将允许我们在 Office 365 中创建用户。这些用户就像一个组织的内部用户。现在使用上述凭据打开 azure 门户。 office 365的所有用户都将导入到active azure directory中。

现在在活动的 Azure 目录中注册一个具有读取用户基本配置文件委派权限的应用程序。记下 client id 、 client secret 和 tenant domain 以获得服务到服务身份验证的访问令牌。此访问令牌可用于获取用户记录,其中将包含邮件字段如 abc@。onmicrosoft.com

虽然这是一个老问题,但我想我会分享我的解决方案来获取登录用户的电子邮件。请注意,此解决方案需要访问用户的 id_token.

调用 /me 端点的响应如下所示:

Object {
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
  "businessPhones": Array [],
  "displayName": "John Doe",
  "givenName": "John",
  "id": "xxxxxx",
  "jobTitle": null,
  "mail": null,
  "mobilePhone": null,
  "officeLocation": null,
  "preferredLanguage": null,
  "surname": "Doe",
  "userPrincipalName": "johndoe_gmail.com#EXT#@johndoegmail.onmicrosoft.com",
}

我们可以看到,这个回复的邮件属性是null。但是,在调用 /token 端点时,我可以通过解码与 access_token 一起传递的 jwt id_token 来获取用户电子邮件。

通过将 decodeJwtToken() 函数(附​​在本 post 末尾)应用于 id_token,我能够从结果中获取用户电子邮件

Object {
  "aio": "xxxxxxxx",
  "amr": Array [
    "pwd",
  ],
  "aud": "xxxxx",
  "email": "johndoe@gmail.com",
  "exp": xxxxxx,
  "family_name": "Doe",
  "given_name": "John",
  "iat": xxxxxx,
  "idp": "live.com",
  "ipaddr": "xxx.xxx.xxx.xxx",
  "iss": "https://sts.windows.net/xxxx/",
  "name": "John Doe",
  "nbf": xxxx,
  "nonce": "xxx",
  "oid": "xxxxxxx",
  "sub": "xxxxx",
  "tid": "xxxxx",
  "unique_name": "live.com#johndoe@gmail.com",
  "uti": "xxxx",
  "ver": "1.0",
}

解码函数如下所示:

decodeIdToken = (token) => {
  var base64Url = token.split('.')[1];
  var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
  var jsonPayload = decodeURIComponent(Buffer.from(base64, 'base64').toString().split('').map(function(c) {
      return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
  }).join(''));

  return JSON.parse(jsonPayload);
};