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

WPF中使用Microsoft Graph API延长过期OAuth 2.0访问令牌方法

问题描述
  • 当前使用Microsoft Graph API的OAuth 2.0客户端凭证模式(client_credentials)生成访问令牌,令牌默认1小时后过期
  • 令牌获取地址:https://login.microsoftonline.com/{Tenant ID}
  • 请求参数:
{ 
    grant_type: "client_credentials", 
    client_id: APP_ID, 
    client_secret: APP_PASSWORD, 
    scope: "https://graph.microsoft.com/.default"
}
  • 现有实现中,调用Graph API从AD拉取用户详情前已添加递归重试逻辑,现在需要在C#中实现延长访问令牌的有效时长,避免频繁过期导致的请求失败
核心说明

首先明确:OAuth 2.0访问令牌本身的过期时间无法在生成后修改,只能通过配置Azure AD应用的令牌生命周期延长最大允许时长,同时在C#代码中通过令牌缓存与自动刷新机制确保使用的始终是有效令牌。

解决方案

1. 在Azure门户配置令牌最大过期时长

客户端凭证模式的令牌默认过期时间为1小时,Azure AD允许将其最长设置为24小时,步骤如下:

  • 登录Azure门户,找到对应的应用注册
  • 进入「令牌配置」选项卡,点击「添加配置」
  • 选择「访问令牌」,设置「过期时间(分钟)」(最大1440分钟,即24小时),保存配置

2. 在C#中用MSAL库自动管理令牌(推荐)

不要手动调用令牌获取接口,使用Microsoft.Identity.Client(MSAL)库来处理令牌的获取、缓存和自动刷新,示例代码如下:

首先安装NuGet包:Microsoft.Identity.Client

然后实现令牌管理类:

using Microsoft.Identity.Client;

public class TokenManager
{
    private readonly IConfidentialClientApplication _clientApp;
    private readonly string[] _scopes = new[] { "https://graph.microsoft.com/.default" };

    public TokenManager(string tenantId, string clientId, string clientSecret)
    {
        _clientApp = ConfidentialClientApplicationBuilder
            .Create(clientId)
            .WithClientSecret(clientSecret)
            .WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
            .Build();
    }

    public async Task<string> GetAccessTokenAsync()
    {
        // 先尝试从缓存获取令牌
        var accounts = await _clientApp.GetAccountsAsync();
        AuthenticationResult result;
        try
        {
            result = await _clientApp.AcquireTokenSilent(_scopes, accounts.FirstOrDefault())
                .ExecuteAsync();
        }
        catch (MsalUiRequiredException)
        {
            // 缓存无有效令牌,重新获取
            result = await _clientApp.AcquireTokenForClient(_scopes)
                .ExecuteAsync();
        }
        return result.AccessToken;
    }
}

3. 改造现有数据库访问代码

将原有直接使用_systemEnvironment.AzureConnectionToken的逻辑,替换为从TokenManager获取有效令牌,确保每次使用的都是未过期的令牌:

// 建议将TokenManager以单例方式注入,避免重复初始化
var tokenManager = new TokenManager(_systemEnvironment.TenantId, _systemEnvironment.AppId, _systemEnvironment.AppPassword);

public async Task<string> SelectInterfaceEndPointAsync(Guid? franchiseRegionUid)
{
    var endPoint = string.Empty;

    try
    {
        using (var cn = new SqlConnection(_systemEnvironment.CommonConnectionString))
        {
            if (_systemEnvironment.IsLiveCommonServer)
            {
                // 实时获取有效令牌
                cn.AccessToken = await tokenManager.GetAccessTokenAsync();
            }

            using (var cmd = new SqlCommand("FranchiseRegion_SelectEndPoint", cn))
            {
                cmd.CommandType = CommandType.StoredProcedure;

                if (franchiseRegionUid != null)
                    cmd.Parameters.Add("@FranchiseRegionUid", SqlDbType.UniqueIdentifier).Value = franchiseRegionUid;

                await cn.OpenAsync();

                using (SqlDataReader reader = await cmd.ExecuteReaderAsync())
                {
                    if (await reader.ReadAsync())
                    {
                        endPoint = General.DbNullString(reader["InterfaceEndPoint"].ToString());
                    }
                }
            }
        }

        return endPoint;
    }
    catch (Exception ex)
    {
        _logMessage.Log(_project, _module, "SelectInterfaceEndPoint", EventLogEntryType.Error, ex, string.Empty, _userId);
        return endPoint;
    }
}
补充说明
  • 不要尝试手动延长已生成令牌的过期时间,这不符合OAuth 2.0规范,Azure AD也不支持修改已签发令牌的有效期
  • MSAL库会自动处理令牌缓存,只有当缓存中的令牌即将过期(或已过期)时才会重新请求新令牌,有效减少不必要的请求
  • 若必须使用手动令牌获取逻辑,需自行维护令牌的过期时间,在每次使用前检查是否即将过期,若过期则重新请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 00:12:38