You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Microsoft Graph API无交互获取全员Teams状态的C#实现疑问

实现无交互获取Teams员工状态的解决方案

可以实现,但需要使用Microsoft Graph的委派权限+无交互认证流,因为Teams用户状态(Presence)API目前仅支持委派权限,应用权限流确实无法调用该接口,以下是具体实现步骤和注意事项:

一、权限配置

  1. 在Azure AD应用注册中添加Microsoft Graph的委派权限 Presence.Read.All
  2. 要求租户管理员对该权限进行租户级同意(因为需要读取所有员工的状态,属于高权限范围)

二、无交互认证方式选择

根据公司的MFA策略选择合适的认证流:

1. 用户名密码流(ROPC)—— 完全无交互(仅适用于未启用MFA的用户)

该流允许应用使用服务账号的用户名和密码直接获取令牌,无需用户交互,但不支持启用MFA的账号,适合公司内部无MFA的服务账号场景。

2. 刷新令牌复用—— 首次交互后无交互

如果公司强制MFA,可先通过设备码流完成一次交互式认证,获取并保存刷新令牌,后续使用刷新令牌无交互获取新的访问令牌。

三、C#代码实现(使用Microsoft Graph SDK)

首先安装必要的NuGet包:

Install-Package Microsoft.Graph
Install-Package Microsoft.Identity.Client

1. ROPC流示例

using Microsoft.Graph;
using Microsoft.Identity.Client;
using System.Collections.Generic;
using System.Threading.Tasks;

class TeamsPresenceTool
{
    static async Task Main(string[] args)
    {
        var clientId = "你的Azure应用ID";
        var tenantId = "你的租户ID";
        var serviceUsername = "内部服务账号用户名";
        var servicePassword = "内部服务账号密码";
        var targetUserIds = new List<string> { "员工ID1", "员工ID2" };

        // 初始化认证客户端
        var pca = PublicClientApplicationBuilder
            .Create(clientId)
            .WithTenantId(tenantId)
            .Build();

        // 获取访问令牌
        var scopes = new[] { "https://graph.microsoft.com/Presence.Read.All" };
        var authResult = await pca.AcquireTokenByUsernamePassword(scopes, serviceUsername, servicePassword).ExecuteAsync();

        // 初始化Graph客户端
        var graphClient = new GraphServiceClient(
            new DelegateAuthenticationProvider(request =>
            {
                request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult.AccessToken);
                return Task.CompletedTask;
            }));

        // 批量获取用户状态
        var presenceRequest = new GetPresencesByUserIdsRequest { UserIds = targetUserIds };
        var presences = await graphClient.Communications.GetPresencesByUserIds(presenceRequest).Request().PostAsync();

        // 处理返回结果
        foreach (var presence in presences.Value)
        {
            Console.WriteLine($"用户{presence.Id}状态:{presence.Availability} - {presence.Activity}");
        }
    }
}

2. 刷新令牌复用示例

using Microsoft.Graph;
using Microsoft.Identity.Client;
using System.Threading.Tasks;

class TeamsPresenceTool
{
    // 从安全存储中读取之前保存的刷新令牌
    private const string SavedRefreshToken = "你的刷新令牌";

    static async Task Main(string[] args)
    {
        var clientId = "你的Azure应用ID";
        var tenantId = "你的租户ID";

        var pca = PublicClientApplicationBuilder
            .Create(clientId)
            .WithTenantId(tenantId)
            .Build();

        var scopes = new[] { "https://graph.microsoft.com/Presence.Read.All" };
        AuthenticationResult authResult;

        // 使用刷新令牌获取新的访问令牌(无交互)
        try
        {
            authResult = await pca.AcquireTokenByRefreshToken(scopes, SavedRefreshToken).ExecuteAsync();
        }
        catch (MsalUiRequiredException)
        {
            // 刷新令牌过期,需要重新交互式认证(仅需一次)
            authResult = await pca.AcquireTokenWithDeviceCode(scopes, deviceCode =>
            {
                Console.WriteLine(deviceCode.Message);
                return Task.CompletedTask;
            }).ExecuteAsync();
            // 将authResult.RefreshToken保存到安全位置,比如Azure Key Vault或本地加密文件
        }

        // 后续调用Graph API的逻辑同ROPC示例
        var graphClient = new GraphServiceClient(
            new DelegateAuthenticationProvider(request =>
            {
                request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult.AccessToken);
                return Task.CompletedTask;
            }));
    }
}

四、关键注意事项

  • Microsoft Graph的Presence API不支持应用权限流,无论添加何种应用权限都无法调用,必须使用委派权限
  • Presence.Read.All权限需要租户管理员同意,否则会返回权限不足的错误
  • ROPC流存在安全风险,仅建议在内部受信任的工具中使用,且避免用于个人用户账号
  • 如果启用MFA,刷新令牌复用是更合规的无交互方案,首次认证后即可长期无交互运行

内容的提问来源于stack exchange,提问作者Peppi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 13:10:08