我在部署应用程序时收到错误“指定的令牌无法与此资源服务器一起使用”,但在本地开发环境中却没有收到错误消息

问题描述 投票:0回答:1

在讨论问题之前,先简要介绍一下我正在开发的系统。我有一个单点登录 (SSO) 系统,其中身份提供商 (IDP) 具有用于用户管理的 API 端点。有一个管理客户端应用程序充当用户管理的前端。用户可以登录并使用Admin Client查看、添加、编辑和删除用户。

在该系统中,授权码流程用于登录并访问客户端及其操作。当用户执行用户管理操作时,管理客户端中的控制器将向 IDP 的 API 端点发送请求。例如,像加载管理客户端的主页一样简单,主页控制器调用一个方法,向 IDP 的 API 端点发出请求,该端点将返回一个 JSON 文件,该文件可以传回主页以显示在表中前端。

管理客户端中的主页控制器已受到策略的保护,该策略在允许用户使用之前检查用户的身份验证和角色,因此管理客户端向 IDP 的 API 端点发出的请求受到使用客户端凭据流的保护。

本系统使用OpenIddict进行身份验证和授权。

这一切在本地开发环境中都运行良好。然而,我们现在正尝试将此系统部署到实时服务器上以对其进行测试/演示,但我们在管理客户端向 IDP 的 API 端点发出的请求中遇到错误。部署应用程序后,用户可以正常登录管理客户端,但无法加载主页,因为对 IDP API 端点的请求返回 401 未经授权的响应。

查看日志,问题似乎与令牌的受众价值有关:

The authentication demand was rejected because the token had no valid audience.

实时系统生成的令牌内容如下所示(通过 jwt.io 解码后):

{
  "iss": "https://company.solutions/SSO_IDP",
  "exp": 1729258266,
  "iat": 1729254666,
  "aud": "https://company.solutions/SSO_IDP",
  "jti": "2a5427c7-b155-496d-8df8-0191649ad580",
  "sub": "adminclient",
  "name": "adminclient",
  "oi_prst": "adminclient",
  "client_id": "adminclient",
  "oi_tkn_id": "f0ae2cd7-aa03-4d3a-89ea-fbe2decf5b24"
}

本地系统生成的token内容如下:

{
  "iss": "https://localhost:7007/",
  "exp": 1729262935,
  "iat": 1729259335,
  "aud": "https://localhost:7007/",
  "jti": "65f8902a-99fb-4f1b-84e4-ef1422fa9b7c",
  "sub": "adminclient",
  "name": "adminclient",
  "oi_prst": "adminclient",
  "client_id": "adminclient",
  "oi_tkn_id": "52352ecf-d942-4e13-fb69-5e15d7ccd956"
}

受众的唯一区别是我们的实时系统在子页面上运行(因此 /SSO_IDP),并且本地主机发行者和受众在末尾有一个“/”,而实时系统没有(这导致之前将 IDP 连接到管理客户端时出现问题)。

它获取此交换的发行者 URL 和受众的方式是通过 appsettings.json 中设置的值。然后在注册客户端时设置客户端的发行者等地方使用该值:

options.AddRegistration(new OpenIddictClientRegistration
{
    ClientId = clientDetails.GetSection("ClientId").Value?.ToString(),
    ClientSecret = clientDetails.GetSection("ClientSecret").Value?.ToString(),
    Issuer = new Uri(clientDetails.GetSection("IssuerUrl").Value?.ToString(), UriKind.Absolute),

    // Other options go here...
});

在IDP中设置受众时:

    .AddValidation(options =>
    {
        options.AddAudiences(new Uri(configuration["AllowedDomains:IssuerUrl"]).GetLeftPart(UriPartial.Authority) + "/");
    });

以及在 IDP 的交换端点中设置令牌的受众。

我的问题是:

  1. 有谁知道这里可能出了什么问题,以及为什么实时应用程序中发送的观众在本地环境中工作时无效?

  2. 有更好的方法来设置这些值吗?或者更重要的是,推荐的做法是什么?

  3. 是否有更好的方法来测试/调查这个问题,以便我可以更好地解决这个问题?

对于这么长的帖子,我深表歉意,但我感谢您提供的任何帮助。预先感谢您。

asp.net jwt authorization access-token openiddict
1个回答
0
投票

这是一个常见问题。我具体不了解Keycloak,但在一些类似的系统中,颁发者值取决于发出身份验证请求时应用程序的来源。

我确信您可以以某种方式将发行者硬编码为静态。在我使用的 IdentityServer 中,我必须对发行者进行硬编码才能使其正常工作。

核心问题是,根据您的部署方式,当用户发出身份验证请求时,问题是一个值,但当客户端应用程序将授权代码交换为实际令牌时,问题是一个不同的值。

参见https://keycloak.discourse.group/t/set-iss-in-jwt-to-custom-value-hardcoded-okay/21687

© www.soinside.com 2019 - 2024. All rights reserved.