Поиск 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();
}
}