【问题标题】:Identity Server 4 - API returns 401 Unauthorised when deployed to serversIdentity Server 4 - API 在部署到服务器时返回 401 Unauthorized
【发布时间】:2020-06-05 19:52:14
【问题描述】:

我正在使用 Blazor Server 应用程序通过 Identity Server 4 进行身份验证,并可以访问 asp.net core 3.1 API。在本地,我有一个设置在端口 5000 上使用 Identity Server,在 5001 上使用 API,在 5002 上使用我的 Blazor 应用程序。

在我们的测试服务器上,我们将这三个服务器都托管在 IIS 中(Blazor 在一台服务器上,API 和 Identity Server 在另一台服务器上)。访问 Authorize 标记的控制器时,我得到 401 Unauthorized。我能够登录,并且我知道 API 仍然可以访问,因为并非所有控制器都需要授权并且数据可以通过。另外,我知道有一个令牌,因为我曾经将它打印到页面上。

在我们的测试环境中,API 不再接受 Identity Server 生成的令牌的原因可能是什么?

这是我的代码示例,如果需要,会很高兴添加更多:

授权控制器

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("api/[controller]")]
[ApiController]
public class Controller : ControllerBase

API 资源

public static IEnumerable<ApiResource> Apis =>
  new ApiResource[]
  {
    new ApiResource("Api", "MyApi")

  };

客户端设置

 public static IEnumerable<Client> Clients =>
        new List<Client>
         {
             //Client
             new Client
            {
                ClientId = "Client",
                ClientSecrets = { new Secret("secret".Sha256()) },

                AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,

                // where to redirect to after login
                RedirectUris = { "http://location:5002/signin-oidc" },

                // where to redirect to after logout
                PostLogoutRedirectUris = { "http://location:5002/signout-callback-oidc" },

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


            }
         };

API 配置

services.AddAuthentication("Bearer")
 .AddJwtBearer("Bearer", options =>
 {
     options.Authority = AuthUrl; // IS loc

     options.Audience = "Api"; 
 });

客户端配置

services.AddSingleton<IDiscoveryCache>(sp =>
            {
                var factory = sp.GetRequiredService<IHttpClientFactory>();
                return new DiscoveryCache(
                    AuthUrl,
                    () => factory.CreateClient());
            });
            services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie("Cookies")
            .AddOpenIdConnect("oidc", options =>
            {
                options.Authority = AuthUrl;
                options.ClientId = ClientID;
                options.ClientSecret = ClientSecret;
                options.ResponseType = "code id_token";
                options.SaveTokens = true;
                options.GetClaimsFromUserInfoEndpoint = true;

                // part 3
                options.Scope.Add("openid");
                options.Scope.Add("offline_access");
                options.Scope.Add("Api");
                options.RequireHttpsMetadata = false;
            });

这是我使用签名凭据的方式

// not recommended for production - you need to store your key material somewhere secure
        if (Environment.IsDevelopment())
        {
            builder.AddDeveloperSigningCredential();
        }
        else
        {
            X509Certificate2 cert = null;
            using (var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine))
            {
                certStore.Open(OpenFlags.ReadOnly);
                var certCollection = certStore.Certificates.Find(
                    X509FindType.FindByThumbprint,
                    "76588d12094bc26991faf9e3eaaa241d973fe72f", // Change this with the thumbprint of your certificate
                    false);

                if (certCollection.Count > 0)
                {
                    cert = certCollection[0];
                }
            }
            builder.AddSigningCredential(cert);
        }

我使用了通过 openssl 生成的自签名证书,并且我也通过不使用 .developerssigningcredentials 在开发人员环境中对其进行了测试。

【问题讨论】:

  • 让我印象深刻的一件事是您的 api 配置中的受众价值。它应该是所使用的客户端的 client_id。另外,您能否在示例令牌中发布 AuthUrl 的值和一些声明?
  • link 表明 .audience 是 API 资源名称/ID? AuthUrl 在我的机器上是“Server.Address:5000”或 localhost:5000。
  • 你试过邮递员来触发请求吗?
  • 类似的结果。 401 Unauthorized with a given Token from Identity Server.
  • 你把http://location:5002/的引用改成服务器上的新地址了吗?

标签: c# api identityserver4 blazor asp.net-core-3.1


【解决方案1】:

确保您网站的 IIS 池可以访问您的私有证书密钥。

您可以尝试使用 LocalSystem

【讨论】:

  • 我认为这不是权限问题,因为身份验证(登录)阶段按预期工作。
猜你喜欢
  • 2020-03-24
  • 1970-01-01
  • 1970-01-01
  • 2011-01-03
  • 1970-01-01
相关资源
最近更新 更多