Как заставить пользователя перейти на веб-сайт для завершения аутентификации, а не на консоль?

Я пытаюсь добавить аутентификацию в свое приложение для Microsoft Graph и добился в этом определенного прогресса. Я следовал этому уроку и у меня все работает.

Но вот как он просит пользователя пройти аутентификацию в данный момент:

void InitializeGraph(Settings settings)
{
    GraphHelper.InitializeGraphForUserAuth(settings,
        (info, cancel) =>
        {
            // Display the device code message to
            // the user. This tells them
            // where to go to sign in and provides the
            // code to use.
            Console.WriteLine(info.Message);
            return Task.FromResult(0);
        });
}

Это работает, и я могу выполнить это, но оно направляет пользователя на консоль, например:

Для входа в веб-браузере откройте страницу https://microsoft.com/devicelogin и введите код RB2RUD56D для аутентификации.

Как я могу заставить его переносить их на веб-сайт вместо того, чтобы пользователь мог продолжить? Функция InitializeGraphForUserAuth:

public static void InitializeGraphForUserAuth(Settings settings,
    Func<DeviceCodeInfo, CancellationToken, Task> deviceCodePrompt)
{
    _settings = settings;

    var options = new DeviceCodeCredentialOptions
    {
        ClientId = settings.ClientId,
        TenantId = settings.TenantId,
        DeviceCodeCallback = deviceCodePrompt,
    };

    _deviceCodeCredential = new DeviceCodeCredential(options);

    _userClient = new GraphServiceClient(_deviceCodeCredential, settings.GraphUserScopes);
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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
104
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Первое, что я заметил, это то, что переменная DeviceCodeInfo info имеет свойство VerificationUri, которое мне и нужно было использовать:

URL-адрес проверки, по которому пользователь должен перейти для аутентификации с использованием кода устройства и учетных данных.

Далее мне нужен был способ открыть этот URL-адрес в браузере пользователя. .NET8 был странным в этом отношении, но я нашел решение в одном из ответов на этот вопрос:

Далее мне нужно было решить вопрос с пользовательским кодом. Это также доступно в DeviceCodeInfo как свойство. Лучшим решением, которое я придумал, было скопировать его в буфер обмена, поскольку невозможно автоматически заполнить форму, добавив параметры в URL-адрес. Как и ожидалось, .NET8 снова оказался немного странным в отношении управления буфером обмена. Ответ на этот вопрос помог:

В итоге я реализовал решение PowerShell для копирования в буфер обмена:

static class WindowsClipboard
{
    public static void SetText(string text)
    {
        var powershell = new Process
        {
            StartInfo = new ProcessStartInfo
            {
                FileName = "powershell",
                Arguments = $"-command \"Set-Clipboard -Value \\\"{text}\\\"\""
            }
        };
        powershell.Start();
        powershell.WaitForExit();
    }

    public static string GetText()
    {
        var powershell = new Process
        {
            StartInfo = new ProcessStartInfo
            {
                RedirectStandardOutput = true,
                FileName = "powershell",
                Arguments = "-command \"Get-Clipboard\""
            }
        };

        powershell.Start();
        string text = powershell.StandardOutput.ReadToEnd();
        powershell.StandardOutput.Close();
        powershell.WaitForExit();
        return text.TrimEnd();
    }
}

Собираем все вместе:

public static async Task InitializeGraph(GraphSettings settings)
{
        await GraphHelper.InitializeGraphForUserAuth(settings,
             (info, cancel)=>
            {
                WindowsClipboard.SetText(info.UserCode);
                System.Diagnostics.Process.Start("explorer", info.VerificationUri.ToString());

                return Task.FromResult(0);
            });
}

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