Одно из моих приложений должно запросить API Graph для получения всех адресов электронной почты данного пользователя, его идентификатора Guid и идентификатора Guid для всех групп, в которые они входят. У меня это работает, но мне нужно сделать как минимум три звонка, что приводит к снижению производительности. Я попытался объединить его только в два запроса, один для токена авторизации и один для выполнения запроса, но до сих пор я не смог объединить параметры $ select с методом «transitiveMemberOf». Вот что у меня так далеко
public class GraphSearcher
{
private readonly IConfiguration _configuration;
private readonly string _clientId;
private readonly string _clientSecret;
private readonly string _tenantId;
public GraphSearcher(IConfiguration configuration)
{
_configuration = configuration;
_clientId = _configuration["AzureAd:ClientId"];
_clientSecret = _configuration["GraphAPI:Secret"];
_tenantId = _configuration["AzureAd:TenantId"];
}
/// <summary>
/// Returns a list of email addresses and a list of group Ids.
/// </summary>
/// <param name="email"></param>
/// <returns>AppUserAttributes object.</returns>
public AppUserAttributes GetUserAttributes(string email)
{
var appUserAttributes = new AppUserAttributes();
if (string.IsNullOrWhiteSpace(email))
return appUserAttributes;
appUserAttributes = GetUserData(email);
return appUserAttributes;
}
// Had to invoke 2 queries, as "transitiveMemberOf" method can't be combined with the other select options.
private AppUserAttributes GetUserData(string email)
{
if (string.IsNullOrWhiteSpace(email))
return null;
var username = email.Split('@')[0];
// This query will return all the emails assigned to the current user, and the user's Active Directory id.
var graphQuery = $"https://graph.microsoft.com/v1.0/{_tenantId}/users?$select=proxyAddresses,mail,id&$filter=proxyAddresses/any(x:startswith(x,'smtp:{username}'))";
var response = GenerateResponse(graphQuery);
var resultString = response.Result.Content.ReadAsStringAsync().Result;
var emailAddresses = ExtractEmailList(resultString);
var json = JObject.Parse(resultString);
var userId = json.SelectTokens("$.value[?(@.id)]").Select(j => j["id"].ToString()).FirstOrDefault();
// This query returns all the groups the user is assigned to.
graphQuery = $"https://graph.microsoft.com/v1.0/{_tenantId}/users/{userId}/transitiveMemberOf";
response = GenerateResponse(graphQuery);
json = JObject.Parse(response.Result.Content.ReadAsStringAsync().Result);
var groupIds = json.SelectTokens("$.value[?(@.id)]").Select(j => j["id"].ToString()).ToList();
return new AppUserAttributes { EmailAddresses = emailAddresses, UserGroupIds = groupIds };
}
private Task<HttpResponseMessage> GenerateResponse(string graphQuery)
{
var authHeaderValue = GenerateAuthenticationHeader();
var response = new HttpClient()
.GetAsync(graphQuery, x => x.Headers.Authorization = authHeaderValue);
return response;
}
private AuthenticationHeaderValue GenerateAuthenticationHeader()
{
var graphAuthenticationToken = GetGraphAuthToken(_clientId, _clientSecret, _tenantId);
var authHeaderValue = new AuthenticationHeaderValue("Bearer", graphAuthenticationToken);
return authHeaderValue;
}
private List<string> ExtractEmailList(string ldapResult)
{
var emailRegex = new Regex(@"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", RegexOptions.IgnoreCase);
var emailList = emailRegex.Matches(ldapResult).Select(m => m.Value).ToList();
return emailList;
}
private string GetGraphAuthToken(string clientId, string clientSecret, string tenant)
{
var authContext = new AuthenticationContext($"https://login.microsoftonline.com/{tenant}/", false);
var tokenRequest = authContext.AcquireTokenAsync("https://graph.microsoft.com", new ClientCredential(clientId, clientSecret));
return tokenRequest.Result.AccessToken;
}
}
public static class HttpHelper
{
public static Task<HttpResponseMessage> GetAsync(this HttpClient httpClient, string uri, Action<HttpRequestMessage> preAction)
{
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
preAction(httpRequestMessage);
return httpClient.SendAsync(httpRequestMessage);
}
}
Я не думаю, что смогу справиться с необходимостью выполнить запрос для получения токена авторизации, но я хотел бы избежать одного звонка, чтобы получить электронные письма и идентификатор пользователя, и другого, чтобы получить идентификаторы группы для этого пользователя. ,
Есть идеи?