Невозможно использовать личную электронную почту с API Graph после установки идентификатора арендатора на «общий»

Я пытаюсь использовать 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);

Буду признателен за любую помощь в этом вопросе. Большое спасибо

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
81
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Первоначально зарегистрируйте одно мультитенантное приложение 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

Привет, Шридеви, спасибо за ответ. Просто для подтверждения: 1. «Поддерживаемый тип приложения» установлен на «Учетные записи в любом каталоге организации... и личные учетные записи Microsoft». 2. У меня есть два разрешения для приложения: «Пользователь.Чтение» и «Календари.Чтение». Оба являются делегированными разрешениями. 3. Я использовал «localhost » в качестве RedirectUrl и отметил кнопку «Разрешить потоки общедоступных клиентов». 4. В моем приложении идентификатор арендатора установлен как «общий», а в моем объекте InteractiveBrowserCredential для RedirectUri установлено значение « localhost». И он по-прежнему разрешает только организационные электронные письма.

Christian Schmid 10.05.2024 14:27

Не могли бы вы подтвердить, как вы передаете область видимости в своем коде и какие значения вы использовали в коде? Пожалуйста, включите и эти строки кода, отредактировав свой вопрос.

Sridevi 10.05.2024 14:29

Я добавил способ использования областей. Подводя итог, у меня есть статическая строка private static readonly string[] s_scopes = new[] { "Calendars.Read" }; И я назначаю ее при создании графового клиента: _client = new GraphServiceClient(service._credential, s_scopes); Спасибо за вашу помощь

Christian Schmid 10.05.2024 14:34

Не могли бы вы попробовать один раз запустить пример кода, который я предоставил в своем ответе, и убедиться, работает ли он в вашей среде или нет?

Sridevi 10.05.2024 14:38

Возможно, стоит упомянуть, что с тех пор, как я опубликовал этот вопрос, я пытался использовать MSAL вместо Azure Identity, и это сработало отлично — я смог использовать личные электронные письма. Однако я бы предпочел не использовать HTTP-запросы и напрямую анализировать ответы JSON, и я не вижу простого способа передать IPublicClientApplicationGraphServiceClient

Christian Schmid 10.05.2024 14:39

Хорошо, да, ваш код работает нормально. Я не уверен, что я делаю по-другому, но похоже, что это как-то связано с моей реализацией. Похоже, что регистрация приложения настроена правильно, и это меня действительно беспокоило. Я очень ценю всю вашу помощь!

Christian Schmid 10.05.2024 14:48

Это может быть отдельный вопрос, но я считаю, что проблема, с которой я столкнулся, связана с тем, что я на самом деле пытаюсь вызвать _client.Me.Calendars.GetAsync(), в котором перечислены все календари, а не только календарь пользователя по умолчанию. Требуются ли какие-либо дополнительные разрешения для чтения списка календарей пользователя?

Christian Schmid 10.05.2024 15:17

Давайте продолжим обсуждение в чате.

Sridevi 10.05.2024 15:24

Другие вопросы по теме

Похожие вопросы