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

如何在Web应用中自动刷新IdentityServer4过期令牌?

实现IdentityServer令牌自动刷新方案

要解决令牌过期需手动刷新页面的问题,核心是利用**刷新令牌(refresh_token)**实现静默自动续期,无需用户手动操作。以下是具体实现步骤:

1. 配置IdentityServer客户端

首先确保你的客户端在IdentityServer中正确配置,允许获取刷新令牌:

  • 在客户端配置类中设置 AllowOfflineAccess = true
  • 将 offline_access 添加到 AllowedScopes 列表中
new Client
{
    ClientId = "your-web-app-client",
    ClientName = "Web Application Client",
    AllowedGrantTypes = GrantTypes.Code,
    RedirectUris = { "https://your-web-app.com/signin-oidc" },
    PostLogoutRedirectUris = { "https://your-web-app.com/signout-callback-oidc" },
    AllowedScopes = { "openid", "profile", "your-api-scope", "offline_access" },
    AllowOfflineAccess = true,
    // 其他配置...
}

2. 前端存储必要令牌信息

登录成功后,除了存储access_token,还需保存:

  • refresh_token:用于换取新的访问令牌
  • expires_at:令牌过期时间戳(计算方式:当前时间 + expires_in秒)

建议根据安全需求选择存储方式:

  • 若前端需直接操作令牌,可使用localStorage(注意防范XSS攻击)
  • 更安全的方式是将refresh_token存在HttpOnly Cookie中,由后端处理刷新逻辑

3. 自动刷新令牌的两种实现方式

方式一:使用官方oidc-client-js库(推荐)

IdentityServer官方提供的oidc-client-js库内置了自动静默刷新功能,无需手动处理复杂逻辑:

  1. 初始化UserManager时开启自动刷新:
const config = {
    authority: "https://your-identityserver.com",
    client_id: "your-web-app-client",
    redirect_uri: "https://your-web-app.com/signin-oidc",
    silent_redirect_uri: "https://your-web-app.com/silent-renew.html", // 空白回调页
    response_type: "code",
    scope: "openid profile your-api-scope offline_access",
    automaticSilentRenew: true, // 开启自动静默刷新
    // 其他配置...
};

const userManager = new Oidc.UserManager(config);
  1. 创建silent-renew.html空白页面,用于处理iframe中的刷新回调:
<!DOCTYPE html>
<html>
<head>
    <title>Silent Renew</title>
</head>
<body>
    <script src="oidc-client.min.js"></script>
    <script>
        new Oidc.UserManager().signinSilentCallback();
    </script>
</body>
</html>

库会自动在令牌过期前发起静默刷新,更新令牌信息,全程无用户感知。

方式二:手动实现刷新逻辑

若不使用官方库,可手动编写逻辑:

  1. 编写令牌过期检查函数:
function isTokenExpiringSoon() {
    const expiresAt = parseInt(localStorage.getItem("expires_at"));
    const currentTime = Date.now() / 1000;
    // 提前60秒触发刷新
    return (expiresAt - currentTime) < 60;
}
  1. 实现刷新令牌请求:
async function refreshToken() {
    const refreshToken = localStorage.getItem("refresh_token");
    if (!refreshToken) return null;

    const response = await fetch("https://your-identityserver.com/connect/token", {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: new URLSearchParams({
            grant_type: "refresh_token",
            client_id: "your-web-app-client",
            client_secret: "your-client-secret", // 机密客户端需提供,公开客户端省略
            refresh_token: refreshToken,
            scope: "your-api-scope offline_access"
        })
    });

    if (response.ok) {
        const data = await response.json();
        // 更新存储的令牌信息
        localStorage.setItem("access_token", data.access_token);
        localStorage.setItem("refresh_token", data.refresh_token);
        localStorage.setItem("expires_at", (Date.now() / 1000) + data.expires_in);
        return data.access_token;
    }
    // 刷新失败(如refresh_token过期),需跳转登录
    window.location.href = "https://your-identityserver.com/connect/authorize?client_id=your-web-app-client&redirect_uri=https://your-web-app.com/signin-oidc&response_type=code&scope=openid profile your-api-scope offline_access";
    return null;
}
  1. 触发刷新的时机:
    • 定时器定时检查:比如每隔30秒检查一次令牌是否即将过期
    • API请求拦截:在每次调用Web应用API前,检查令牌状态,若即将过期则先刷新

关键注意事项

  • 静默刷新依赖用户的IdentityServer会话未过期(即用户浏览器中仍有IdentityServer的登录Cookie)
  • 若前端与IdentityServer跨域,需确保IdentityServer的CORS配置允许前端域名访问/connect/token端点
  • 机密客户端的client_secret不应暴露在前端代码中,建议由后端代理刷新请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:33:27