Identity Server 4 令牌到期 Api 与 ClientApp

Identity Server 4 token expiration Api vs ClientApp

我目前正在构建一个带有 authentication/authorization 的 WebApp 以访问它并访问多个 WebAPI,所有这些都指向一个 Identity Server 4 主机。 我遵循了 IdentityServer4 的官方文档及其演示,以及客户端身份验证、令牌生成、用户登录、API 被令牌成功调用,显然一切正常,但最近我注意到一段时间后不活动时,对 API 的调用开始收到 401,但客户端应用程序仍然使用相同的标记。

是这样的:

  1. 启动浏览器进行调试
  2. 用某个用户登录
  3. 转到调用一个 API 为其检索数据的视图
  4. 继续导航和测试,其他一切正常

现在,问题(在前面的第 4 步之后)

  1. 停止调试但保持浏览器启动并运行(保留 cookie)
  2. 更改代码,实现新的东西(基本上是在消磨一些时间)
  3. 再次启动调试
  4. 在已打开的浏览器上使用相同的 sessions/cookie,尝试在应用程序上导航工作正常,不需要重新登录
  5. 导航到将使用当前令牌调用 API 的视图,在以前没有的情况下给了我 401

我发现令牌已过期,Visual Studio 输出指出了这一点(同时检查 https://jwt.io/ 上的令牌我可以确认日期时间)。 为什么相同的令牌对 ClientApp 可以正常工作,而调用 API 却不行?由于 API 的调用,我是否需要手动生成新令牌?

我使用的配置是:

---客户申请---

new Client
{
    ClientId = "idWebApp",
    ClientSecrets = new List<Secret> { new Secret("secret".Sha256()) },

    AllowedGrantTypes = GrantTypes.Hybrid,
    AllowAccessTokensViaBrowser = false,

    EnableLocalLogin = true,

    RedirectUris = { "http://localhost:5901/signin-oidc" },
    FrontChannelLogoutUri = "http://localhost:5901/signout-oidc",
    PostLogoutRedirectUris = { "http://localhost:5901/signout-callback-oidc" },

    AllowOfflineAccess = true,

    AllowedScopes = new List<string>
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        IdentityServerConstants.StandardScopes.OfflineAccess,
        "apiAccess",
    },

    RequireConsent = false,
}

---API资源---

(仅使用简单的 ctor 以 'Name' 进行初始化)

new ApiResource("apiAccess")

---自定义声明---

new IdentityResource()
{
    Name = "appCustomClaims",
    UserClaims = new List<string>()
    {
        "customRole"
    }
}

---ClientApp的启动代码---

services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
    .AddCookie("Cookies")
    .AddOpenIdConnect("oidc", options =>
    {
        options.Authority = "http://localhost:5900";
        options.RequireHttpsMetadata = false;

        options.ClientId = "idWebApp";
        options.ClientSecret = "secret";
        options.ResponseType = "code id_token";

        options.Scope.Add("profile");
        options.Scope.Add("offline_access");
        options.ClaimActions.MapUniqueJsonKey("offline_access", "offline_access");

        options.Scope.Add("appCustomClaims");
        options.ClaimActions.MapJsonKey("customRole", "customRole");

        options.Scope.Add("apiAccess");

        options.GetClaimsFromUserInfoEndpoint = true;
        options.SaveTokens = true;
        options.TokenValidationParameters.RoleClaimType = "customRole";
    });

Why the same token works fine for the ClientApp while invoking the API doesn't?

两件事:

  1. 访问令牌的过期时间与您的操作无关。

JWT 令牌一旦颁发就无法更改。默认情况下,令牌会在 3600 秒后过期。

  1. 应用程序与api的区别:应用程序使用cookies,api一个bearer token。

cookie 有自己的过期逻辑。这意味着它在不同的时间过期,与访问令牌的过期时间无关,并且还可以保持活动状态,因为可以更新 cookie,这与 JWT 访问令牌不同。

对于 offline_access,您需要使用刷新令牌获取新的访问令牌。正如所解释的 .