My colleague ran into this issue while attempting to retrieve a user's email address. I am not an AAD expert (nor speak on behalf of Microsoft) but I have been crossing paths with AAD in side projects for a while. During this time I saw conflicting information about which attribute to deem the 'source of truth' for user emails.
Background
My first thought was also the mail attribute but to my surprise this was empty on occasion (some sources explain that this is the Exchange mail provisioned for the user at time of creation). The otherMails (or Alternative Email as it appears in the Portal) offered no help either. UPNs looked promising, until you realise that guests from other tenants or those who signed up via an external identity provider will have #ext# in the UPN, making it inconvenient to work with, as @Sushrut Paranjape points out.
What worked
This example shows how to get the user's associated identities (local and federated) via the Identity object (not returned by default)
GET https://graph.microsoft.com/v1.0/users?$select=displayName,identities
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(displayName,identities)",
"value": [
{
"displayName": "Test User",
"identities": [
{
"signInType": "userPrincipalName",
"issuer": "contoso.onmicrosoft.com",
"issuerAssignedId": "user@example.com"
}
]
}, ...
]
}
✨ issuerAssignedId = Unique identifier assigned to the user by the issuer. It is an email address depending on the signInType (some providers may only offer usernames).
We then do some logic at our API to get issuerAssignedId where signInType = "emailAddress".
In closing
It is also worth noting that we were using Azure Active Directory B2C, which works really well with external (federated) identity providers. All in all, I can understand why this isn't as straight forward as one would expect. To ensure consistency, the above is simply the best way to abstract each identity provider's fields into its fundamental attributes so that developers working with AAD can reliably access the desired data.
I hope this adds some clarity to the picture. Please let me know if this was helpful.