2017-05-09 39 views
2

我开发的认证服务器提供的令牌被用来消耗使用IdentityServer4我们的API。 我正在使用MongoDB作为数据库,我让用户可以获取令牌,并且更安全我正在使用自定义证书来加密令牌。 这是我Startup.cs我AuthenticationServer的样子:身份服务器4 - 禁用发现端点

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(本地主机: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'。 at 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看起来是发现端点,看看端点在哪里解密令牌(我想这将是userinfo_endpoint)。

我的观点是:

  • 看来,发现端点用来获取如何使用认证服务器信息(对我来说是有道理的,开放的API),但是对我们来说,我们不发展和开放的API,所以我们的客户将只是我们已经达成的协议,我们会提前告诉他们端点,我们很可能会限制IP地址。
  • 有什么办法停用发现端点和设置的API证书正确地解密令牌。

也许我错过了整个图片,我说的是愚蠢的事情,但我很乐意了解背后的概念。 在此先感谢

回答

0

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

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

我并不完全确定IdentityServer4.AccessTokenValidation,但是IdentityServer3.AccessTokenValidation只能将ValidationMode设置为Local,所以它只是下载一次公钥。

0

有可能使发现端点关闭/不可用,并且仍然验证令牌。

您需要实现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也能够接收令牌并验证签名。

0

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

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

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

如果您的发现端点不可用,那么整个令牌服务可能不起作用,这可能是一个更大的问题。

+0

这是否意味着拥有可用的发现端点不会造成安全风险? ..我来自WCF,我不得不禁用端点的元数据。 – Learner