Reputation: 3419
I have followed the documentation to find a registered User by Sign In Name.
The sample shows the following code to return any user with a Sign In Name [email protected]
:
var users = await graphClient.Users
.Request()
.Filter("identities/any(c:c/issuerAssignedId eq '[email protected]' and c/issuer eq 'contoso.onmicrosoft.com')")
.GetAsync();
Now I am trying to implement a search, which should search users without entering the full signInName
. Since the filter appears to be OData, I tried to enhance it using the contains
method:
var users = await graphClient.Users
.Request()
.Filter($"identities/any(c:contains(c/issuerAssignedId,'j.smith') and c/issuer eq 'contoso.onmicrosoft.com') ")
.Top(5)
.GetAsync();
Now I receive the following error when I run this new query:
Status Code: BadRequest
Microsoft.Graph.ServiceException: Code: Request_BadRequest
Message: An unknown function with name 'contains' was found. This may also be a key lookup on a navigation property, which is not allowed.
Do I have a typo somewhere or is contains
not allowed? I don't think the issuerAssignedId
is a lookup or a navigation property. Since I'm working with Azure AD B2C, the $search
function is also not working according to the same documentation page, so I am now stuck.
What is the way to search users in Azure AD B2C?
I have found two more StackOverflow articles talking about this, but they are quite old. In one of them, a Microsoft employee points out that one could use the startswith
operator.
I have tried implementing it like this, but it also throws an error.
.Filter($"identities/any(a:startswith(a/issuerAssignedId,'{username}') and a/issuer eq '{issuer}') ")
Status Code: BadRequest
Microsoft.Graph.ServiceException: Code: Request_BadRequest
Message: Unsupported property or property value or combination of property and operation occured
More sources:
Upvotes: 1
Views: 1047
Reputation: 342
I use the following code to get the User by a username or login email to query the Azure AD B2C.
string usernameOrEmail = "[email protected]";
string aadB2CIssuerDomain = "yourtenant.onmicrosoft.com";
public async Task<User[]> GetGraphApiUsersByUsernameEmail(string usernameOrEmail)
{
var users = await _graphServiceClient
.Users
.GetAsync(requestConfiguration =>
{
requestConfiguration.QueryParameters.Filter = $"identities/any(c:c/issuerAssignedId eq '{usernameOrEmail}' and c/issuer eq '{aadB2CIssuerDomain}')";
});
foreach (var user in users.Value.ToList().Select(e => new
{
e.DisplayName,
e.Id,
e.Identities,
e.Mail,
e.UserPrincipalName,
}))
{
Console.WriteLine(JsonConvert.SerializeObject(user));
}
return users?.Value.ToArray();
}
Hope it helps. Kind regards
Upvotes: 1
Reputation: 30903
With the note that contains
operator is currently not supported on any MS Graph queries, there is a workaround with startsWith
.
The Microsoft Graph implementation for lookup the identities
property is limited to providing exact values for both issuerAssignedId
and issuer
.
A workaround that I have implemented is to keep the issuerAssignedId
in additional extension attribute. This is relatively easy to implement if you use custom policies. But if you use user flows, it will be error prone as there is no direct way to record this value as additional attribute. You have to, basically, constantly query MS Graph for (delta at best!) users and update custom attribute based on issuerAssignedId.
Upvotes: 1