Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search for user in Azure Active directory group using graph api

I would like to have some kind of people picker functionality with auto complete features in my asp.net mvc 5 app to search for a user in a specific Azure AD group. It's a demo "todo app" that allows to assign a todo to a user that is member of a the group.

I tried with both the Graph API directly and the Azure Graph Client library but I don't seem to find a way to achieve what I want. The graph api allows to get the members of a group but adding filter "startswith" fails as when adding the filter the api returns only directory object which don't include for example DisplayName property... the client library doesn't help much either except for the batch functionality which offers a way but with a lot of overhead... I then would have to get a filtered resultset of user regardless of group membership (using User List stuff in the api), all members of the group and then fish out using Linq the correct result set.... would work fine for dev/testing but in production with a couple of hundred users this would be insane...

Any ideas or suggestions would be much appreciated. Thanks!

EDIT

Below my code that is called from client side Javascript to search for user;

  • AccessGroupId is the Azure AD group used to authorize users. Only members of this group can access the web app which I handle in custom OWin Middleware
  • The method is intented to be used to find a user in that group

Code works fine as below only there is no filtering applied which is the intentaion with the input parameter pre (which comes from a textbox in the ui). I get all the members of the access group.

public async Task<JsonResult> FindUser(string pre) 
{
    string AccessGroupId = ConfigurationManager.AppSettings["AccessGroupId"];
    AuthenticationContext authCtx = new AuthenticationContext(String.Format(CultureInfo.InvariantCulture, "{0}/{1}", SecurityConfiguration.LoginUrl, SecurityConfiguration.Tenant));
    ClientCredential credential = new ClientCredential(SecurityConfiguration.ClientId, SecurityConfiguration.AppKey);
    AuthenticationResult assertionCredential = await authCtx.AcquireTokenAsync(SecurityConfiguration.GraphUrl, credential);
    var accessToken = assertionCredential.AccessToken;

    var graphUrl = string.Format("https://graph.windows.net/mytenant.onmicrosoft.com/groups/{0}/members?api-version=2013-11-08, AccessGroupId );
    HttpClient client = new HttpClient();
    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, graphUrl);
    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    HttpResponseMessage response = await client.SendAsync(request);
    String responseString = await response.Content.ReadAsStringAsync();
    JObject jsonReponse = JObject.Parse(responseString);
    var l = from r in jsonReponse["value"].Children()
            select new
            {
                UserObjectId = r["objectId"].ToString(),
                UserPrincipalName = r["userPrincipalName"].ToString(),
                DisplayName = r["displayName"].ToString()
            };
    //users = Newtonsoft.Json.JsonConvert.DeserializeObject<List<User>>(responseString);
    return Json(l, JsonRequestBehavior.AllowGet);
}

When I add a filter to the same api call instead of returning the members (users, groups and/or contacts), it returns directory objects (that doesn't have displayName) which are not really usefull in the above code, unless I would query the api again (in batch) to retrieve the users displayname but that looks like a lot of overhead to me.

var graphUrl = string.Format("https://graph.windows.net/mytenant.onmicrosoft.com/groups/{0}/members?api-version=2013-11-08&$filter=startswith(displayName,'{1}')", AccessGroupId, pre);
like image 269
Xavierk Avatar asked Nov 10 '22 00:11

Xavierk


1 Answers

I'd highlight two possible approaches:

  1. Execute requests to Graph API using a custom JS library. You'd need still need to care for accesstokens and have a look at ADAL.js

A sample app (not finalized as of this writing) available at: AzureADSamples WebApp-GroupClaims-DotNet

Have a look at AadPickerLibrary.js

  1. Try using ActiveDirectoryClient

It would look something like:

public async Task<JsonResult> FindUser(string pre) {

ActiveDirectoryClient client = AADHelper.GetActiveDirectoryClient();

IPagedCollection<IUser> pagedCollection = await client.Users.Where(u => u.UserPrincipalName.StartsWith(pre, StringComparison.CurrentCultureIgnoreCase)).ExecuteAsync();

if (pagedCollection != null)
{
    do
    {
        List<IUser> usersList = pagedCollection.CurrentPage.ToList();

        foreach (IUser user in usersList)
        {
            userList.Add((User)user);
        }

        pagedCollection = await pagedCollection.GetNextPageAsync();

    } while (pagedCollection != null);
}

return Json(userList, JsonRequestBehavior.AllowGet);        

}

More detailed sample is available at: AzureADSamples WebApp-GraphAPI-DotNet

like image 60
Milen Avatar answered Nov 14 '22 23:11

Milen