当图形服务调用返回用户已添加到租户时,是否不能保证



我的应用程序有一个用户管理界面,用于由对我们的Azure租户没有足够权限的用户进行委托管理。当一个新用户被添加到应用程序中时,我们会检查该用户是否已经存在于租户中,如果不存在,我们会邀请他们。类似这样的东西:

var existingUser = // Try to find the user in the graph by email
if (existingUser == null)
{
// User doesn't exist, add and get them.
var invitation = new Invitation
{
SendInvitationMessage = false,
InvitedUserEmailAddress = user.Email,
InviteRedirectUrl = _inviteSettings.AppUrl
};
await _graphClient
.Invitations
.Request()
.AddAsync(invitation);
existingUser = // Get the user from the graph by email...
}

用户需要多长时间才能通过图形调用可用?

我在这里的一条评论中非正式地看到,这可能需要5到10秒。(使用PowerShell,所以可能无关?(MS文档说:

邀请用户时,将创建一个用户实体(userType Guest(并且现在可以用于控制对资源的访问。

此外,响应示例显示了从请求返回的必要属性。

然而,问题是在运行时,用户并不总是能立即找到。有时需要两到三次尝试才能成功完成,而完成的时间已经超过了上面提到的10秒。

当图形服务调用返回用户已添加到租户时,是否不能保证?


注意:我从"更新了标题;用户需要多长时间才能通过图形调用可用">因为我更关心的是担保而不是典型的时间跨度。


似乎无法保证新邀请的外部用户可以通过所有图形端点/调用使用,尽管邀请中创建了访客用户。该用户已经填充了电子邮件和其他一些详细信息,但仍然无法找到:

// Filter by email to avoid calculating the ugly
// user principal names for external users.
await _graphClient
.Users
.Request()
.Filter($"mail eq '{email}'")
.GetAsync();

这显然适用于域用户和租户"中的访客;足够长";(不管这意味着什么(但不是那些刚刚被邀请的人。幸运的是,还有另一种方法。

图形调用返回的Invite包括来宾用户的只读副本。您可以获取InvitedUser.Id属性值,并对Users端点进行调用,这显然会使用户立即可用:

await _graphClient
.Users[invite.InvitedUser.Id]
.Request()
.GetAsync();

其他注意事项:修复此问题暴露了为外部用户分配应用程序角色的另一个问题。尝试尽快分配角色总是导致CCD_ 4为"0";不是有效的参考更新";使用:

await _graphClient
.ServicePrincipals[principalId]
.AppRoleAssignedTo
.Request()
.AddAsync(assignment);

这是微软推荐的方法,所以我试着坚持它,并添加了一些粗略的重试逻辑来看看我看到了什么(使用时风险自负(:

private async Task<R> RetryTask<R>(Func<Task<R>> func, int max, int delay = 1000, int n = 0)
{
try
{
if (max - n == 1) return default(R);
await Task.Delay(n * delay);
return await func();
}
catch (Exception e)
{
return await RetryTask(func, max, delay, n + 1);
}
}

问题是它在等待10秒后无法完成任务;从可用性的角度来看太长了。所以,我尝试了不推荐的方式,并且。我找不到建议背后的原因,所以我不能谈论针对Users而不是ServicePrincipals这样做的风险。

await _graphClient
.Users[userId]
.AppRoleAssignments
.Request()
.AddAsync(assignment);

我用图形api在我这边测试它,以邀请访客用户,并且一旦api请求完成,用户就可以在AD中使用了(几乎没有等待时间(。经过一些测试,我认为你的问题与AD中访客用户可用的时间无关,问题是由你的代码异步运行引起的。

代码await _graphClient.Invitations.Request().AddAsync(invitation);需要几秒钟的时间才能完成邀请来宾操作。但是下一行代码existingUser =将立即执行,即使前一行代码尚未完成。所以它会响应找不到用户的情况。

糟糕的是,我找不到请求await _graphClient.Invitations.Request().AddAsync(invitation);的任何属性,这可以帮助我们知道请求是否完成。所以我们可以使用一个不太好的解决方案,代码应该是这样的:

await graphClient.Invitations.Request().AddAsync(invitation);
User user = null;
while (user == null)
{
Thread.Sleep(1000);
try
{
user = await graphClient.Users["email"].Request().GetAsync();
}catch (Exception e)
{
user = null;
}
}
Console.WriteLine(user.DisplayName);

顺便说一下,为了避免while的无限循环,您还可以添加一个变量countcount每次加1,当count > 60时,存在while循环。

最新更新