19

I want to add User to a Group but I don't have the User's id, I only have the email address.

Here is the code:

User userToAdd = await graphClient
    .Users["objectID"]
    .Request()
    .GetAsync();

await graphClient
    .Groups["groupObjectID"]
    .Members
    .References
    .Request()
    .AddAsync(userToAdd);

Can someone help how do I retrieve ObjectId (User ID) from an email address using Microsoft Graph?

Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
sidi shah
  • 889
  • 2
  • 7
  • 7

7 Answers7

13

You can look up a user a few different ways.

From the /users endpoint you can either use their id (the GUID assigned to each account) or their userPrincipalName (their email alias for the default domain):

// Retrieve a user by id
var user  = await graphClient
    .Users["00000000-0000-0000-0000-000000000000"]
    .Request()
    .GetAsync();

// Retrieve a user by userPrincipalName
var user  = await graphClient
    .Users["user@tenant.onmicrosoft.com"]
    .Request()
    .GetAsync();

If you're using either the Authorization Code or Implicit OAuth grants, you can also look up the user who authenticated via the /me endpoint:

var user = await graphClient
    .Me
    .Request()
    .GetAsync();
Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
12

Besides these correct answers above.

userPrincipalName or id is not the external email address. That was my case when registration is done manually. You can use this filter:

var user = await _graphClient.Users
    .Request()
    .Filter($"identities/any(c:c/issuerAssignedId eq '{email}' and c/issuer eq 'contoso.onmicrosoft.com')")
    .GetAsync();

src: https://learn.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=csharp

Using this configuration to create an user:

Microsoft.Graph.User graphUser = new Microsoft.Graph.User
{
    AccountEnabled = true,
    PasswordPolicies = "DisablePasswordExpiration,DisableStrongPassword",
    PasswordProfile = new PasswordProfile
    {
            ForceChangePasswordNextSignIn = false,
            Password = accountModel.Password,
        },
        Identities = new List<ObjectIdentity>
        {
            new ObjectIdentity()
            {
                SignInType = "emailAddress",
                Issuer ="contoso.onmicrosoft.com",
                IssuerAssignedId = email
            }
        },
};
Sachin Joseph
  • 18,928
  • 4
  • 42
  • 62
boehlefeld
  • 201
  • 2
  • 7
2

You can retrieve user's details from Graph API using id or userPrincipalName (which is an email address).

From Microsoft Graph API reference:

GET /users/{id | userPrincipalName}

Have you tried to use the email address as objectID?

FIL
  • 1,148
  • 3
  • 15
  • 27
1

If you need retrieve a guest user may use:

public static async Task<User> GetGuestUserByEmail(string email)
{
        try
        {
            var request = await graphClient
                .Users
                .Request()
                .Filter($"userType eq 'guest' and mail eq '{email}'") // apply filter
                .GetAsync();

            var guestUsers = request.CurrentPage.ToList();
            var user = guestUsers.FirstOrDefault();
            return user;
        }
        catch (ServiceException ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
            return null;
        }
 }
LuisEduardox
  • 364
  • 4
  • 9
1

There actually is no truly reliable way to do this. Email addresses in AAD are not unique. The UPN is often an email address, and it is unique, but there's a nasty catch: If the person happens to have a long email address AND they're a guest user, the UPN appears to be the email truncated to 54 characters, then have #EXT# tacked on, and it can even be changed after the fact to have the #EXT# removed where it can be up to 64 characters before the @ symbol, and doesn't have to be anything resembling their actual email address.

The only way you're supposed to actually be able to find them is with their user object's GUID.

https://learn.microsoft.com/en-us/answers/questions/81053/user-principal-name-and-ext.html

Dragoon
  • 723
  • 6
  • 13
0

There is a reliable way to get the emails address using the Open ID mechanism. With openid as a scope, you can get the userinfo_endpoint endpoint from https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration

GET https://graph.microsoft.com/oidc/userinfo (this endpoint shouldn't be hard coded)

{
 "sub": "uniqueid",
  "name": "Name",
  "family_name": "Name",
  "given_name": "Name",
  "picture": "https://graph.microsoft.com/v1.0/me/photo/$value",
  "email": "email@example.com"
}

https://learn.microsoft.com/en-us/azure/active-directory/develop/userinfo

Suhas Sharma
  • 71
  • 1
  • 3
0

Such a seemingly simple thing and yet so complex. My strategy:

var users = await graphClient.Users.Request()
   .Filter($"userPrincipalName eq '{targetEmail}' or mail eq '{targetEmail}'")
   .GetAsync();

If all you have is the email address you can't get around the possibility of more than one hit and letting your user pick the right one. Which makes sense, since if you're ever adding people to something in the Azure portal or DevOps it's the same thing.

But at least this way you should have both your internal users (via userPrincipalName) and guests (via mail) covered in one query.

Emperor Eto
  • 2,456
  • 2
  • 18
  • 32