Поиск Active Directory B2C по пользовательскому свойству на пользователе

Мы используем B2C и сохраняем номера клиентов в качестве поля расширения для пользователей. Один пользователь может иметь одного или нескольких клиентов, и они хранятся в строке, разделенной запятыми.

То, что я делаю сейчас, крайне неэффективно:  1. Получить всех пользователей  2. Получить свойства расширения для каждого пользователя  3. Проверьте, есть ли у них требуемое свойство расширения, и если он содержит клиента, которого я хочу.  4. Создайте список пользователей, которых я хочу.

Adclient - это IActiveDirectoryClient

var users = (await GetAllElementsInPagedCollection(await AdClient.Users.ExecuteAsync())).ToList();
var customersUsers = users.Where(user => user.AccountEnabled.HasValue && user.AccountEnabled.Value).Where(user =>
    {
        var extendedProperty = ((User) user).GetExtendedProperties().FirstOrDefault(extProp => extProp.Key == customersExtendedProperty.Name).Value?.ToString();
        return extendedProperty != null && extendedProperty.Contains(customerId);
    }).ToList();

Я хочу иметь возможность сделать это в одном запросе в ActiveDirectory с помощью AdClient. Если я попробую это, я получаю ошибки, что методы не поддерживаются, что имеет смысл, поскольку я предполагаю, что запрос создается за кулисами для запроса Active Directory.

Изменить - дополнительная информация:

Я смог запросить Graph API следующим образом:

var authContext = await ActiveDirectoryClientFactory.GetAuthenticationContext(AuthConfiguration.Tenant,
AuthConfiguration.GraphUrl, AuthConfiguration.ClientId, AuthConfiguration.ClientSecret);
var url = $"https://graph.windows.net:443/hansaborgb2c.onmicrosoft.com/users?api-version=1.6&$filter={customersExtendedProperty.Name} eq '{customerId}'";
var users = await _graphApiHttpService.GetAll<User>(url, authContext.AccessToken);

Однако в моем примере мне нужно использовать substringof для фильтрации, но это не поддерживается Azure Graph API.

Ответ 1

Я не использую эту библиотеку, но мы делаем очень похожий поиск, используя Graph API. Я создал фильтр, который будет искать пользователей, которые соответствуют двум значениям атрибутов расширения, которые я ищу. Фильтр выглядит следующим образом:

var filter = $"$filter={idpExtensionAttribute} eq '{userType.ToString()}' and {emailExtensionAttribute} eq '{emailAddress}'";

Мы также использовали REST-вызовы через PowerShell для API-интерфейсов Graph, которые возвратят желаемых пользователей. URI с соответствующим фильтром выглядит следующим образом:

https://graph.windows.net/$AzureADDomain/users?`$filter=extension_d2fbadd878984184ad5eab619d33d016_idp eq '$idp' and extension_d2fbadd878984184ad5eab619d33d016_email eq '$email'&api-version=1.6

Оба этих параметра возвращают всех пользователей, соответствующих критериям фильтра.

Ответ 2

Я бы использовал обычный класс DirectorySearcher из System.DirectoryServices

private void Search()
{
    // GetDefaultDomain as start point is optional, you can also pass a specific 
    // root object like new DirectoryEntry ("LDAP://OU=myOrganisation,DC=myCompany,DC=com");
    // not sure if GetDefaultDomain() works in B2C though :(
    var results = FindUser("extPropName", "ValueYouAreLookingFor", GetDefaultDomain());

    foreach (SearchResult sr in results)
    {
        // query the other properties you want for example Accountname
        Console.WriteLine(sr.Properties["sAMAccountName"][0].ToString());
    }
    Console.ReadKey();
}

private DirectoryEntry GetDefaultDomain()
{   // Find the default domain
    using (var dom = new DirectoryEntry("LDAP://rootDSE"))
    {
        return new DirectoryEntry("LDAP://" + dom.Properties["defaultNamingContext"][0].ToString());
    }
}

private SearchResultCollection FindUser(string extPropName, string searchValue, DirectoryEntry startNode)
{
    using (DirectorySearcher dsSearcher = new DirectorySearcher(startNode))
    {
        dsSearcher.Filter = $"(&(objectClass=user)({extPropName}={searchValue}))";
        return dsSearcher.FindAll();
    }
}