使用显式网络凭据从 .Net Core API 调用 SSO-Enabled API

Calling SSO-Enabled API From .Net Core API Using Explicit Network Credentials

我正在将 WinForms 应用程序迁移到 .Net Core (3.1) API,我 运行 遇到了调用 SSO-protected 的功能的问题API 在我们的网络中。

在 WinForms 应用程序中,我有以下内容:

public async void Authenticate()
{
        var wi = System.Security.Principal.WindowsIdentity.GetCurrent();
        var wic = wi.Impersonate();

        try
        {
            // Initial request to grab cookies and redirect endpoint
            var apiEndPoint = $"https://{_host}{_apiPath}";
            var cookieRedirectRequest = new HttpRequestMessage(HttpMethod.Get, apiEndPoint);
            var response = await _httpClient.SendAsync(cookieRedirectRequest);
            if (response != null)
            {
                var cookieContainer = new CookieContainer();
                foreach (var cookie in response.Headers.GetValues("Set-Cookie"))
                {
                    var parsedCookie = cookie.ToCookie();
                    parsedCookie.Domain = TARGET_DOMAIN;
                    cookieContainer.Add(parsedCookie);
                }
                var redirectURL = response.Headers.GetValues("Location").FirstOrDefault();

                // Add the cookies to the client to continue the authentication
                _httpClient = new HttpClient(new HttpClientHandler()
                {
                    UseDefaultCredentials = true,
                    AllowAutoRedirect = true,
                    ClientCertificateOptions = ClientCertificateOption.Automatic,
                    UseCookies = true,
                    CookieContainer = cookieContainer
                });

                // Second request to grab code and state values
                var codeAndStateRequest = new HttpRequestMessage(HttpMethod.Get, redirectURL);
                response = await _httpClient.SendAsync(codeAndStateRequest);
...

对 API 的初始调用将我们重定向到 SSO-authentication 页面。我使用该初始响应中的 cookie 创建我自己的请求,以便我可以传递正确的凭据并取回适当的 SSO 令牌(在最后一行 returns 返回令牌的 SendSync 调用的响应),这然后,我用于对 API.

的未来请求进行身份验证

我正在尝试使用服务帐户在 .NET Core 中重新创建此功能,而不是进行 WindowsIdentity 模拟,我正在尝试显式设置我的 HttpClientHandler 的 NetworkCredentials 属性:

                handler = new HttpClientHandler()
                {
                    UseDefaultCredentials = false,
                    Credentials = new NetworkCredential("svc_acct_username", "svc_act_pass", "mydomain"),
                    AllowAutoRedirect = true,
                    ClientCertificateOptions = ClientCertificateOption.Automatic,
                    UseCookies = true,
                    CookieContainer = cookieContainer,                        
                };

但是,我从第二个请求中得到的响应是 401。

这与我以前在原始应用程序中得到的结果一致——我最初会得到一个带有“WWW-Authenticate: Negotiate”header 的 401,但随后会有一个自动传入网络凭据的后续请求,我会得到 200。我没有收到带有 .Net Core 中的凭据的第二个请求。

我尝试了此处建议的凭据缓存解决方案: https://github.com/dotnet/runtime/issues/24490 但这并没有奏效。

提前感谢你们能给我的任何帮助。我卡住了!

快速编辑: 通过简单地显式设置 HttpClientHandler 的 Credentials 属性 并设置 UseDefaultCredentials = false,我可以在我的 WinForms 应用程序中重新创建 .Net Core 行为。因此,通过设置 UseDefaultCredentials 会发生一些神奇的事情,在使用显式凭据时似乎无法重新创建。

我在 co-worker 的帮助下完成了这项工作!问题是,当您使用显式网络凭据时,您会丢失“协商”身份验证类型,这是我们的 SSO-endpoint 所要求的。通过使用 CredentialCache 对象并显式设置协商 auth-type,调用有效!

var credCache = new CredentialCache { { new Uri("https://example.com"), "Negotiate", new NetworkCredential("svc_acct_user", "svc_acct_password", "mydomain") } };

// Add the cookies to the client to continue the authentication
handler = new HttpClientHandler()
{   
    UseDefaultCredentials = false,
    Credentials = credCache,
    AllowAutoRedirect = true,
    ClientCertificateOptions = ClientCertificateOption.Automatic,
    UseCookies = true,
    CookieContainer = cookieContainer,                        
};