在模拟其他用户时请求Kerberos票证时安全软件包中没有凭据

时间:2018-08-21 14:40:16

标签: c# kerberos impersonation sspi kerberos-delegation

上下文:使用OWIN中间件,在IIS和IIS Rewrite-rules之上以C#内置的自定义反向代理/ API网关。

目标:我希望代理首先对传入的请求进行身份验证(这很容易在IIS中配置)。有了身份可用,OWIN中间件应基于经过身份验证的用户声明某些内容。但是,此后,该请求应发送到后端API,也是经过Windows验证的

我尝试的解决方案::在进一步发送请求之前,OWIN中间件应模拟经过身份验证的身份,请求Kerberos票证并将其放入Authorization标头(如Negotiate XXXXX.....)。 / p>

以下是使用C#标准库的代码:

var identity = (WindowsIdentity) context.Request.User.Identity;
using (var impersonation = identity.Impersonate())
{
    var spn = "HTTP/" + backendHostname; // e.g. HTTP/myapi.mydomain.com
    var tokenProvider = new KerberosSecurityTokenProvider(spn, TokenImpersonationLevel.Impersonation);
    var token = tokenProvider.GetToken(TimeSpan.FromMinutes(1)) as KerberosRequestorSecurityToken;
    var ticketBytes = token.GetRequest();
    var ticket = Convert.ToBase64String(ticketBytes);
    context.Request.Headers.Append("Negotiate", ticket);
}

这是我尝试使用NSSPI的另一种实现方式:

var identity = (WindowsIdentity) context.Request.User.Identity;
using (var impersonation = identity.Impersonate())
{
    var clientCredentials = new ClientCurrentCredential(PackageNames.Kerberos);
    var client = new ClientContext(
        clientCredentials,
        "HTTP/" + backendHostname, // e.g. HTTP/myapi.mydomain.com
        ContextAttrib.MutualAuth |
        ContextAttrib.InitIdentify |
        ContextAttrib.Confidentiality |
        ContextAttrib.ReplayDetect |
        ContextAttrib.SequenceDetect |
        ContextAttrib.Connection |
        ContextAttrib.Delegate
    );
    var clientStatus = client.Init(null, out var tokenBytes);
    var token = Convert.ToBase64String(tokenBytes);
    context.Request.Headers.Append("Negotiate", token);
}

两个实现都引发异常,归结为以下Win32错误:

  

安全软件包中没有可用的凭据

重要信息:

  • 代理服务器托管在IIS中,并在服务帐户下运行(假设为srv_ApiGateway
  • IIS中的
  • useAppPoolCredentials设置为True(否则IIS甚至无法使用Kerberos验证初始请求)
  • 已设置服务帐户(srv_ApiGateway),以便在AD中委派给Trust this user for delegation to any service (Kerberos only)
  • 在两种实现方式中,删除模拟并仅在服务帐户正常工作时索取票证(仅用于FYI)
  • 代理和后端API均具有正确的SPN(使用Kerberos正确验证了直接请求)。
  • WindowsIdentity.GetCurrent().ImpersonationLevel中的
  • using返回ImpersonationLevel.Impersonation(可能应该是Delegation

有人对导致此问题的原因有任何建议吗?如何解决这个双重跃点的反向代理用例?任何帮助表示赞赏:)

1 个答案:

答案 0 :(得分:1)

未将模拟级别设置为Delegation的原因是无效的票证。出于某些原因,即使该域已列入白名单(根据these docs),Google Chrome仍不会为该用户请求委派票证。尝试使用IE,然后再使用Chrome,即使不是真正的解决方案,也可以。