【问题标题】:Identity server 4 - deactivate the discovery endpoint身份服务器 4 - 停用发现端点
【发布时间】:2017-05-13 19:37:23
【问题描述】:

我正在开发一个身份验证服务器来传递令牌,以使用 IdentityServer4 来使用我们的 API。 我使用 MongoDB 作为允许用户获取令牌的数据库,为了更安全,我使用自定义证书来加密令牌。 这就是我的AuthenticationServer Startup.cs 的样子:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

    var cert = new X509Certificate2(Path.Combine(_environment.ContentRootPath, "cert", "whatever.pfx"), "whatever");

    services.AddIdentityServer().AddSigningCredential(cert)
            .AddInMemoryApiResources(Config.Config.GetApiResources());

    services.AddTransient<IUserRepository, UserRepository>();

    services.AddTransient<IClientStore, ClientStore>();
    services.AddTransient<IProfileService, UserProfileService>();
    services.AddTransient<IResourceOwnerPasswordValidator, UserResourceOwnerPasswordValidator>();
    services.AddTransient<IPasswordHasher<User.Model.User>, PasswordHasher<User.Model.User>>();

}

如您所见,我对那些执行客户端身份验证和密码验证的接口进行了自定义实现。这工作正常。

然后我用生成的令牌保护另一个应用程序,我在那里定义它必须使用IdentityServerAuthetication(localhost:5020 是我的AuthenticationServer 运行的地方)

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseCors("CorsPolicy");

        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
        {
            Authority = "http://localhost:5020",
            RequireHttpsMetadata = false,
            ApiName = "MyAPI",
            RoleClaimType = JwtClaimTypes.Role
        });

        app.UseMvc();
    }

一切正常,但如果我关闭 AuthenticationServer,我会从我正在保护的 API 中收到此错误:

System.InvalidOperationException:IDX10803:无法从“http://localhost:5020/.well-known/openid-configuration”获取配置。 在 Microsoft.IdentityModel.Protocols.ConfigurationManager`1.d__24.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.d__1.MoveNext() 失败:Microsoft.AspNetCore.Server.Kestrel[13]

所以看起来 API 将前往 discovery 端点,以查看解密令牌的端点在哪里(我猜应该是 userinfo_endpoint)。

我的观点是:

  • 似乎发现端点用于获取有关如何使用身份验证服务器的信息(对我来说,开放 API 是有意义的),但在我们的例子中,我们没有开发和开放 API,所以我们的客户端只是我们有协议的,我们会提前告诉他们端点,我们很可能会通过 IP 地址进行限制。
  • 有什么方法可以停用发现端点并在 API 上设置证书以正确解密令牌。

也许我错过了完整的画面并且我在说一些愚蠢的事情,但我很乐意理解背后的概念。 提前致谢

【问题讨论】:

    标签: c# mongodb openid identityserver4


    【解决方案1】:

    发现端点可能关闭/不可用,但仍会验证令牌。

    您需要实现 IConfigurationManager 并将其传递给 IdentityServerAuthenticationOptions 内的 JwtBearerOptions 对象。

    下面是一些示例代码:

    public class OidcConfigurationManager : IConfigurationManager<OpenIdConnectConfiguration>
    {
        public OidcConfigurationManager()
        {
            SetConfiguration();
        }
        private OpenIdConnectConfiguration _config;
        public Task<OpenIdConnectConfiguration> GetConfigurationAsync(CancellationToken cancel)
        {
            return Task.FromResult<OpenIdConnectConfiguration>(_config);
        }
        public void RequestRefresh()
        {
        }
    
        private void SetConfiguration()
        {
            // Build config from JSON
            var configJson =
                @"{""issuer"":""http://localhost/id"",""jwks_uri"":""http://localhost/id/.well-known/openid-configuration/jwks"",""authorization_endpoint"":""http://localhost/id/connect/authorize"",""token_endpoint"":""http://localhost/id/connect/token"",""userinfo_endpoint"":""http://localhost/id/connect/userinfo"",""end_session_endpoint"":""http://localhost/id/connect/endsession"",""check_session_iframe"":""http://localhost/id/connect/checksession"",""revocation_endpoint"":""http://localhost/id/connect/revocation"",""introspection_endpoint"":""http://localhost/id/connect/introspect"",""frontchannel_logout_supported"":true,""frontchannel_logout_session_supported"":true,""scopes_supported"":[""openid"",""profile"",""api1"",""offline_access""],""claims_supported"":[""sub"",""name"",""family_name"",""given_name"",""middle_name"",""nickname"",""preferred_username"",""profile"",""picture"",""website"",""gender"",""birthdate"",""zoneinfo"",""locale"",""updated_at""],""grant_types_supported"":[""authorization_code"",""client_credentials"",""refresh_token"",""implicit"",""password""],""response_types_supported"":[""code"",""token"",""id_token"",""id_token token"",""code id_token"",""code token"",""code id_token token""],""response_modes_supported"":[""form_post"",""query"",""fragment""],""token_endpoint_auth_methods_supported"":[""client_secret_basic"",""client_secret_post""],""subject_types_supported"":[""public""],""id_token_signing_alg_values_supported"":[""RS256""],""code_challenge_methods_supported"":[""plain"",""S256""]}";
            _config = new OpenIdConnectConfiguration(configJson);
    
            // Add signing keys if not present in json above
            _config.SigningKeys.Add(new X509SecurityKey(cert));
        }
    }
    

    现在将该配置对象传递给 IdentityServerAuthenticationOptions 中的一些 JwtBearerOptions(有点烦人,但这是我知道的唯一方法)

    var identityServerOptions = new IdentityServerAuthenticationOptions
    {
        Authority = "http://localhost:5020",
        RequireHttpsMetadata = false,
        ApiName = "MyAPI",
        RoleClaimType = JwtClaimTypes.Role,
    
    };
    var jwtBearerOptions = new JwtBearerOptions() {ConfigurationManager = new OidcConfigurationManager()};
    var combinedOptions = CombinedAuthenticationOptions.FromIdentityServerAuthenticationOptions(identityServerOptions);
    combinedOptions.JwtBearerOptions = jwtBearerOptions;
    app.UseIdentityServerAuthentication(combinedOptions);
    

    现在,即使 OIDC 发现端点关闭,您的 API 也将能够接收令牌并验证签名。

    【讨论】:

      【解决方案2】:

      API 验证中间件在启动时下载发现文档的副本,然后(至少默认情况下)每 24 小时下载一次。

      如果签名验证失败,它可能会重新触发下载(以适应计划外的密钥翻转)。

      您可以静态定义所有配置值 - 但您将失去动态配置更新的所有好处。

      如果您的发现端点不可用,则可能整个令牌服务无法正常工作,这可能是一个更大的问题。

      【讨论】:

      • 这是否意味着发现端点可用不会带来安全风险? .. 我来自 WCF,我必须禁用端点的元数据。
      【解决方案3】:

      IdentityServer 需要您的 X509 证书的公钥来验证 access_token。它正在使用发现端点来获取该公钥,并且不时刷新保存的公钥(因为公钥可能会更改)。

      如果无法访问 IdentityServer,您的 API 无法保证 access_token 有效。您可以增加对access_token 验证请求结果的缓存。

      我不完全确定 IdentityServer4.AccessTokenValidation,但使用 IdentityServer3.AccessTokenValidation,您只能将 ValidationMode 设置为 Local,因此它只下载一次公钥。

      【讨论】:

        猜你喜欢
        • 2023-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-17
        • 1970-01-01
        • 2017-06-26
        • 1970-01-01
        • 2017-04-07
        相关资源
        最近更新 更多