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

时间:2017-11-17 06:16:12

标签: azure-active-directory microsoft-graph azure-ad-graph-api

我可以访问用户的accessToken,并使用GET https://graph.microsoft.com/v1.0/me标题拨打Authorization: Bearer <token>

但是,在回复正文中,我得到了这样的内容:

{
    "@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,此响应正文中的userPrincipalName恰好是用户的电子邮件地址。但是,这有来自Microsoft的docs

  

虽然UPN和电子邮件共享相同的格式,但用户的UPN值可能与用户的电子邮件地址相同,也可能不同。

在发起用户的登录请求时,我们会请求"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);
}

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

3 个答案:

答案 0 :(得分:3)

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

  1. 已在内部部署AD上设置,然后使用AD Connect
  2. 同步到Azure AD
  3. 已为云用户分配了Office 365许可证(和邮箱),此时为此许可用户设置了mail属性。
  4. 如果用户没有O365邮箱/许可证,您还可以通过userPrincipalName,displayName等搜索用户。$ filter支持OR运算符。

    希望这有帮助,

答案 1 :(得分:0)

使用以下链接在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的所有用户都将导入到活动的Azure目录中。

现在在活动的azure目录中注册具有“读取用户”基本配置文件委派权限的应用程序。记下客户端ID,客户端密钥和租户域,以获取用于服务到服务认证的访问令牌。此访问令牌可用于获取用户记录,该记录将包含abc @ .onmicrosoft.com的邮件字段

答案 2 :(得分:0)

尽管这是一个老问题,但我想我将分享我的解决方案来获取登录用户的电子邮件。请注意,此解决方案需要访问用户的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",
}

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

通过对id_token应用decodeJwtToken()函数(在本文末尾附上),我可以从结果中获取用户电子邮件

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);
};