Я пытаюсь использовать Microsoft Graph API для доступа к информации календаря в приложении, которое я создаю, с использованием C# и .NET. Насколько я понимаю, вы должны установить TenantId при настройке аутентификации на «общий», так как это позволит электронным письмам Microsoft или личным электронным письмам использовать регистрацию приложения.
Он работал, как и ожидалось, с моей личной электронной почтой, которую я использовал для разработки, но затем перестал разрешать личные электронные письма:
Я не уверен, связано ли это с изменениями, которые я внес в свой код, или с изменениями в серверной части, но я не могу решить эту проблему.
Вот соответствующий код:
private const string TENANT_ID = "common";
private const string CLIENT_ID = "<CLIENT_ID>";
private static readonly string[] s_scopes = new[] { "Calendars.Read" };
private static readonly FileInfo s_authPath = new FileInfo("./csOutlookStorage");
private static readonly string s_tokenCacheName = "OwsAuthToken";
private GraphServiceClient _client;
public bool AccountLinked => s_authPath.Exists;
public async Task InitializeAsync(CancellationToken token = default)
{
var credentialOptions = new InteractiveBrowserCredentialOptions()
{
TenantId = TENANT_ID,
ClientId = CLIENT_ID,
TokenCachePersistenceOptions = new TokenCachePersistenceOptions() { Name = s_tokenCacheName },
RedirectUri = new Uri("http://localhost:3006")
};
InteractiveBrowserCredential credential;
if (!AccountLinked)
{
credential = new InteractiveBrowserCredential(credentialOptions);
var authRecord = await credential.AuthenticateAsync(token);
using (var authRecordStream = s_authPath.Open(FileMode.Create))
{
await authRecord.SerializeAsync(authRecordStream);
}
}
...
_client = new GraphServiceClient(credential, s_scopes);
Буду признателен за любую помощь в этом вопросе. Большое спасибо





Первоначально зарегистрируйте одно мультитенантное приложение Entra ID с «Поддерживаемым типом учетной записи», как показано ниже:
Чтобы получить доступ к информации календаря, обязательно назначьте Calendars.Read разрешение типа «Делегированный» в приложении, как показано ниже:
При использовании интерактивного потока вам необходимо добавить http://localhost/ в качестве URI перенаправления на платформах «Мобильные и настольные приложения» и включить общедоступные клиенты, как показано ниже:
Чтобы получить доступ к информации календаря через Graph API путем входа в личные учетные записи, вы можете использовать приведенный ниже пример кода:
using Azure.Identity;
using Microsoft.Graph;
using Newtonsoft.Json;
using Formatting = Newtonsoft.Json.Formatting;
class Program
{
static void Main(string[] args)
{
GetCalendar().Wait();
}
static async Task GetCalendar()
{
var scopes = new[] { "Calendars.Read" };
// Multi-tenant apps can use "common",
var tenantId = "common";
// Value from app registration
var clientId = "appId";
var options = new InteractiveBrowserCredentialOptions
{
TenantId = tenantId,
ClientId = clientId,
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
RedirectUri = new Uri("http://localhost"),
};
var interactiveCredential = new InteractiveBrowserCredential(options);
var graphClient = new GraphServiceClient(interactiveCredential, scopes);
var result = await graphClient.Me.Calendar.GetAsync();
var json = JsonConvert.SerializeObject(result, Formatting.Indented);
Console.WriteLine("Get calendar API response:");
Console.WriteLine(json);
}
}
Когда вы запустите код, он откроет браузер и попросит вас выбрать учетную запись следующим образом:
Здесь вы также можете выбрать личную учетную запись для входа в систему, что приведет к запросу согласия на следующем шаге, как показано ниже:
После подтверждения согласия, если аутентификация прошла успешно, вы увидите экран ниже:
Когда вы вернетесь в приложение сейчас, вы можете найти ответ API календаря в консоли вывода следующим образом:
Использованная литература:
Выберите поставщика аутентификации Microsoft Graph — Microsoft Graph
Получите календарь — Microsoft Graph v1.0
Не могли бы вы подтвердить, как вы передаете область видимости в своем коде и какие значения вы использовали в коде? Пожалуйста, включите и эти строки кода, отредактировав свой вопрос.
Я добавил способ использования областей. Подводя итог, у меня есть статическая строка private static readonly string[] s_scopes = new[] { "Calendars.Read" }; И я назначаю ее при создании графового клиента: _client = new GraphServiceClient(service._credential, s_scopes); Спасибо за вашу помощь
Не могли бы вы попробовать один раз запустить пример кода, который я предоставил в своем ответе, и убедиться, работает ли он в вашей среде или нет?
Возможно, стоит упомянуть, что с тех пор, как я опубликовал этот вопрос, я пытался использовать MSAL вместо Azure Identity, и это сработало отлично — я смог использовать личные электронные письма. Однако я бы предпочел не использовать HTTP-запросы и напрямую анализировать ответы JSON, и я не вижу простого способа передать IPublicClientApplicationGraphServiceClient
Хорошо, да, ваш код работает нормально. Я не уверен, что я делаю по-другому, но похоже, что это как-то связано с моей реализацией. Похоже, что регистрация приложения настроена правильно, и это меня действительно беспокоило. Я очень ценю всю вашу помощь!
Это может быть отдельный вопрос, но я считаю, что проблема, с которой я столкнулся, связана с тем, что я на самом деле пытаюсь вызвать _client.Me.Calendars.GetAsync(), в котором перечислены все календари, а не только календарь пользователя по умолчанию. Требуются ли какие-либо дополнительные разрешения для чтения списка календарей пользователя?
Давайте продолжим обсуждение в чате.
Привет, Шридеви, спасибо за ответ. Просто для подтверждения: 1. «Поддерживаемый тип приложения» установлен на «Учетные записи в любом каталоге организации... и личные учетные записи Microsoft». 2. У меня есть два разрешения для приложения: «Пользователь.Чтение» и «Календари.Чтение». Оба являются делегированными разрешениями. 3. Я использовал «localhost » в качестве RedirectUrl и отметил кнопку «Разрешить потоки общедоступных клиентов». 4. В моем приложении идентификатор арендатора установлен как «общий», а в моем объекте InteractiveBrowserCredential для RedirectUri установлено значение « localhost». И он по-прежнему разрешает только организационные электронные письма.