Я пытаюсь добавить аутентификацию в свое приложение для 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);
}
Первое, что я заметил, это то, что переменная 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);
});
}