首页 > 解决方案 > IdentityServer3 - 客户端证书验证

问题描述

我有 IdentityServer3,我正在尝试将他们的原始样本WebHost (minimal)作为服务器和Console Client Credentials Flow using Certificate客户端运行,因为我想测试客户端是否可以通过使用 X509 指纹而不是共享密钥来验证 IdS3 来获取访问令牌。

我遇到的问题是我收到错误响应:invalid_client. 显然,这是因为 IdS3 没有收到传入请求的证书,所以它认为令牌请求是无效的(我通过添加自定义SecretParser和检查environment参数对此进行了测试,并且没有用于解析它的ssl.ClientCertificate值) X509CertificateSecretParser.

我只是将两个不同的 Visual Studio 实例中的两个项目运行到 IIS Express 中,而没有修改项目上的任何其他内容。在这件事上我有什么遗漏吗?为了使这项工作,我还需要设置什么?

标签: asp.netoauth-2.0openid-connectidentityserver3

解决方案


您需要做的第一件事是在 IIS Express 中启用客户端证书。

您可以通过编辑此文件来做到这一点:

.vs\config\applicationhost.config

改变

<access sslFlags="None" />

<access sslFlags="Ssl, SslNegotiateCert" />

现在 IIS Express 支持客户端证书,但它也会检查证书是否受信任。

示例证书 Client.pfx 不能开箱即用。

您可以让 Windows 信任此证书的颁发者(不推荐),也可以使用以下代码从证书存储中加载现有证书:

        X509Store store = new X509Store(StoreLocation.CurrentUser);
        store.Open(OpenFlags.ReadOnly);
        string thumb = "<thumbprint>";
        X509Certificate2Collection cers = store.Certificates.Find(X509FindType.FindByThumbprint, thumb, false);
        X509Certificate2 cert = null;
        if (cers.Count > 0)
        {
            cert = cers[0];
        }
        store.Close();

您还需要将此证书的指纹放入 Identity Server 客户端列表中的 ClientSecret 属性中。

这是您需要更改的示例代码:

            new Client
            {
                ClientName = "Client Credentials Flow Client",
                Enabled = true,
                ClientId = "clientcredentials.client",
                Flow = Flows.ClientCredentials,

                ClientSecrets = new List<Secret>
                    {
                        new Secret("secret".Sha256()),
                        new Secret
                        {
                            Value = "<your thumbprint here>",
                            Type = Constants.SecretTypes.X509CertificateThumbprint,
                            Description = "Client Certificate"
                        },
                    },

                AllowedScopes = new List<string>
                    {
                        "read",
                        "write"
                    },

                Claims = new List<Claim>
                    {
                        new Claim("location", "datacenter")
                    }
            },

推荐阅读