我刚刚开始使用 Azure,我的第一次尝试是使用图形客户端 API 进行简单的数据显示。简单来说,我想获取员工的 Teams 状态并以某种图形方式将其显示在表单上。
我试图尽可能基本,所以当我尝试下载示例时,我不需要 UWP 项目,只需要基本的 winform(控制台目前可以工作)。我确实从项目中借用了一些东西来编译,但我收到错误:
MsalUiRequiredException:没有帐户或登录提示传递到 AcquireTokenSilent 调用。
这是完整的代码,我显然遗漏了一些东西......什么?这是一个应用程序,应该能够访问 Graph API 以获取用户读取和 getPresence 调用以显示当前状态,并需要使用登录。我可以看到 Graph Explorer 有一个 token 并正在查看 postman 集有一些方法可以在没有交互的情况下做到这一点,但没有一个文档是明确的。我将继续研究这个问题,也许看看我是否可以让 postman 工作,这可能会有所帮助,但幕后的访问权限对我来说并不清楚。
public partial class Form1 : Form
{
//Set the scope for API call to user.read
private string[] scopes = new string[] { "user.read" };
private const string ClientId = "my client id";
private const string Tenant = "my tenant id";
private const string Authority = "https://login.microsoftonline.com/" + Tenant;
// The MSAL Public client app
private static IPublicClientApplication PublicClientApp;
private static string MSGraphURL = "https://graph.microsoft.com/v1.0/";
private static AuthenticationResult authResult;
public Form1()
{
InitializeComponent();
PublicClientApp = PublicClientApplicationBuilder.Create(ClientId).WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient").Build();
callMe();
}
private async void callMe()
{
// Sign-in user using MSAL and obtain an access token for MS Graph
GraphServiceClient graphClient = await SignInAndInitializeGraphServiceClient(scopes);
// Call the /me endpoint of Graph
User graphUser = await graphClient.Me.Request().GetAsync();
Console.WriteLine(graphUser.Id);
var graphu2 = await graphClient.Users["my email address"].Request().GetAsync();
}
private async Task<GraphServiceClient> SignInAndInitializeGraphServiceClient(string[] scopes)
{
GraphServiceClient graphClient = new GraphServiceClient(MSGraphURL,
new DelegateAuthenticationProvider(async (requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", await getToken(scopes));
}));
return await Task.FromResult(graphClient);
}
public async Task<string> getToken(string[] scopes)
{
PublicClientApp = PublicClientApplicationBuilder.Create(ClientId)
.WithAuthority(Authority)
.WithLogging((level, message, containsPii) =>
{
Console.WriteLine($"MSAL: {level} {message} ");
}, LogLevel.Warning, enablePiiLogging: false, enableDefaultPlatformLogging: true)
.Build();
IEnumerable<IAccount> accounts = await PublicClientApp.GetAccountsAsync().ConfigureAwait(false);
IAccount firstAccount = accounts.FirstOrDefault();
try
{
authResult = await PublicClientApp.AcquireTokenSilent(scopes, firstAccount)
.ExecuteAsync();
}
catch (MsalUiRequiredException ex)
{
// A MsalUiRequiredException happened on AcquireTokenSilentAsync. This indicates you need to call AcquireTokenAsync to acquire a token
Console.WriteLine($"MsalUiRequiredException: {ex.Message}");
authResult = await PublicClientApp.AcquireTokenInteractive(scopes)
.ExecuteAsync()
.ConfigureAwait(true);
}
return authResult.AccessToken;
}
最佳答案
抱歉,但我将忽略您的代码并将其分解为更简单的代码。
using Azure.Identity;
using Microsoft.Graph;
namespace StackoverflowAnswer
{
internal class Program
{
static void Main(string[] args)
{
MainAsync().Wait();
}
static async Task MainAsync()
{
var tenantId = "YOUR_TENANT_ID";
var clientId = "YOUR_CLIENT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";
try
{
string[] scopes = { "https://graph.microsoft.com/.default" };
ClientSecretCredential clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret);
GraphServiceClient graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var users = await graphClient.Users.Request().GetAsync();
foreach (var user in users)
Console.WriteLine(user.UserPrincipalName);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
上面的许多代码都取自以下文档,因为一旦您通过身份验证,SDK 的其余部分就基本相同。不过,这可能会很棘手,具体取决于您想做的事情的具体性质......
https://github.com/microsoftgraph/msgraph-sdk-dotnet/blob/dev/docs/tokencredentials.md
这也有帮助......
另请确保您已在 Azure 门户中为应用程序分配了所需的 API 权限...
...并确保您已为您的应用程序设置了客户端 key 。如果您有客户端 ID,那么您显然已经做到了这一点...
https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app
更新
现在,对于使用 Presence API,这有点棘手。
虽然看起来如此,但 Presence API 不支持应用程序权限。它有一个应用程序权限,但简单地说,它不起作用。此用户语音链接提供了对此的见解。
因此,您需要做的是将委派权限应用到您注册的应用程序。
因此,您需要在代码中使用 UsernamePasswordCredential
而不是 ClientSecretCredential
,并在实例化 GraphServiceClient
时替换它。
UsernamePasswordCredential usernamePasswordCredential = new UsernamePasswordCredential("<USERNAME>", "<PASSWORD>", tenantId, clientId);
此外,您需要确保相关用户已授予使用该权限的访问权限。如果它是面向用户的应用程序,那么他们会登录并看到一个问题,以批准您设置的权限,但因为它不是,所以您需要转到企业应用程序部分Azure AD,找到您的应用,转到权限,然后为您的租户按下授予管理员同意按钮。
有人可能有比上面更好的方法,但这是我能找到的唯一方法。这意味着如果有人知道客户端 ID 以及如何进行身份验证,他们就可以执行与您相同的 API。
无论如何,这将允许您了解码织中所有用户的状态。
关于c# - 无法通过基本 C# 应用程序的 Azure 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74146546/