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

使用Microsoft.Identity.Client同时获取Access Token与Refresh Token

关于获取Refresh Token及刷新Access Token的问题处理

问题场景

我使用tenant id、client id、client secret、redirect uri及为用户生成的authorization code等参数,需要同时获取access token和refresh token,但当前API未返回refresh token,仅能获取access token和过期时间。

使用的代码如下:

ConfidentialClientApplicationOptions options = new ConfidentialClientApplicationOptions();
options.ClientId = clientId;
options.TenantId = tenantId;
options.ClientSecret = clientSecret;
options.RedirectUri = redirectUri;

ConfidentialClientApplicationBuilder builder = ConfidentialClientApplicationBuilder.
    CreateWithApplicationOptions(options);
IConfidentialClientApplication app = builder.Build();
AcquireTokenByAuthorizationCodeParameterBuilder acquireTokenBuilder = 
    app.AcquireTokenByAuthorizationCode(ServiceConstants.ALL_SCOPE_AUTHORIZATIONS.Split(' '), authorizationCode);
AuthenticationResult result = await acquireTokenBuilder.ExecuteAsync();
string accessToken = result.AccessToken;
// NO string refreshToken = result.RefreshToken

疑问:很多示例中AuthenticationResult里都有RefreshToken,但我的没有。请问这是什么原因?如何获取refresh token?另外,access token过期后,仅持有access token、tenant id、client id、密钥(或证书)及redirect uri,如何重新生成access token?


一、未返回Refresh Token的原因及解决方法

核心原因:未请求offline_access权限范围

Microsoft Identity Platform的规则是:只有在授权请求中明确包含offline_access范围,服务端才会返回Refresh Token。你的代码中使用的ServiceConstants.ALL_SCOPE_AUTHORIZATIONS大概率没有包含这个范围,导致无法获取Refresh Token。

解决步骤

  1. 修改权限范围,添加offline_access
    更新代码中的scopes参数,将offline_access加入请求范围:

    // 拆分原有范围并追加offline_access
    var scopes = ServiceConstants.ALL_SCOPE_AUTHORIZATIONS.Split(' ')
                                                          .Append("offline_access")
                                                          .ToArray();
    AcquireTokenByAuthorizationCodeParameterBuilder acquireTokenBuilder = 
        app.AcquireTokenByAuthorizationCode(scopes, authorizationCode);
    AuthenticationResult result = await acquireTokenBuilder.ExecuteAsync();
    // 此时result.RefreshToken会正常返回
    string refreshToken = result.RefreshToken;
    
  2. 确认应用配置无限制
    检查Azure AD中应用的配置:

    • 重定向URI与代码中options.RedirectUri完全一致;
    • 应用类型为机密客户端(你使用ConfidentialClientApplication符合要求,默认允许颁发Refresh Token)。

二、Access Token过期后的刷新方式

场景1:持有有效Refresh Token

直接使用Refresh Token请求新的Access Token,代码示例:

// 传入需要的权限范围和之前获取的Refresh Token
var result = await app.AcquireTokenByRefreshToken(scopes, refreshToken)
                      .ExecuteAsync();
// 获取新的Access Token和更新后的Refresh Token
string newAccessToken = result.AccessToken;
string newRefreshToken = result.RefreshToken; // 建议保存新的Refresh Token,旧的可能失效

场景2:无Refresh Token(仅持有过期的Access Token等信息)

这种情况无法直接刷新Token,因为过期的Access Token无法用来获取新的凭证。必须重新引导用户完成授权流程,获取新的Authorization Code,再通过Code换取新的Access Token和Refresh Token(务必确保这次请求包含offline_access范围)。

更简便的方式:利用MSAL令牌缓存自动刷新

MSAL SDK内置令牌缓存机制,只要缓存中存在有效Refresh Token,调用AcquireTokenSilent时会自动检测Token状态,过期则自动刷新:

try
{
    // user为之前授权的用户对象,可从缓存中获取
    var result = await app.AcquireTokenSilent(scopes, user)
                          .ExecuteAsync();
    string accessToken = result.AccessToken;
}
catch (MsalUiRequiredException)
{
    // 缓存无有效Token,需重新引导用户授权
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 13:15:51