使用 AD/ADFS 和 .NET Native Client 的 SSO

问题描述 投票:0回答:1

我的问题是关于 Active Directory (AD)、Active Directory 联合身份验证服务 (ADFS)、单点登录 (SSO) 和 SAML。

我们有一个具有以下规格的客户端/服务器应用程序: - 客户端:基于.NET 4.7.2和C#的WPF .NET Native Client - 服务器:基于Java Spring的REST服务

一个主要要求是使用 AD/ADFS 进行 SSO。 在最好的情况下,用户应该无缝/静默地进行身份验证。

主要限制是基于Windows Server 2012 R2的AD和ADFS。

在下图中,您可以了解我们计划如何使用 ADFS 实施 SSO。

SSO 场景

  • .NET Native Client 尝试在没有身份验证的情况下使用 REST 服务。
  • REST 服务将 .NET 本机客户端重定向到 ADFS 服务器。
  • .NET Native Client 尝试使用当前登录的用户凭据(Windows 登录)获取 SAML 令牌。
  • 如果当前用户被授予 ADFS 服务器响应和 SAML 令牌。
  • .NET Native Client 获取 SAML 令牌并将其传递给 REST 服务。
  • 如果 SAML 令牌被接受,则授予用户访问权限。
  • 如果 SAML 令牌未被接受,用户应在应用程序中看到登录屏幕。

此时,我对 .NET Native Client 中的 SSO 和 ADFS 完全感到困惑。 我找不到任何合适的演示等。 许多演示或用例都与 ASP.NET 有关,但几乎没有与本机客户端有关。 我开始怀疑我关于 AD/ADFS 和 SAML 的 SSO 的假设是否不正确。

我开始使用了解 ADFS 和 ADFS 简介中描述的虚拟机构建 AD-ADFS 实验室。 然后我尝试使用 ADFS 服务器但无法完成。

我正在看这个图书馆:

经过 1 周的研究,我的头开始旋转:

  • 我需要 WIF 吗?
  • WCF 怎么样?

我知道有 OAuth。我知道 Windows Server 2012 并不是该方案的最新版本和最佳版本。但要求和限制直接来自我们的客户。

  • 我能做什么?
  • 我可以阅读或尝试什么?
  • 还有其他图书馆吗?
  • 有例子吗?

更新

我能够使用 WS-Trust 与我的 ADFS 服务器“对话”并获得 SAML 令牌。

private static void Main(string[] args)
    {
        string adfs = "https://ad-fs.adlab.local";
        string adfsEndpoint = "https://ad-fs.adlab.local/adfs/services/trust/13/usernamemixed";
        string appServer = "https://ad-server.adlab.local/sampapp/";

        var factory = new WSTrustChannelFactory(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), adfsEndpoint);
        factory.TrustVersion = TrustVersion.WSTrust13;

        var channelCredentials = factory.Credentials;

        channelCredentials.UserName.UserName = "Administrator@adlab";
        channelCredentials.UserName.Password = "SsoLab2019";
        channelCredentials.SupportInteractive = false;

        RequestSecurityToken rst = new RequestSecurityToken
        {
            RequestType = RequestTypes.Issue,
            AppliesTo = new EndpointReference(appServer),
            KeyType = KeyTypes.Bearer
        };

        var channel = factory.CreateChannel();

        try
        {
            var token = (GenericXmlSecurityToken)channel.Issue(rst);
            Console.Write(token.TokenXml.OuterXml);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

        Console.ReadKey();
    }

不,我必须弄清楚如何才能让 SAML 令牌保持沉默/无缝。

c# single-sign-on saml adfs wif
1个回答
0
投票
//This code will get you the SAML Token for SAP Odata Services in C# 
protected HttpClient Client
{
    get
    {
        if (client == null)
        {
            handler = new HttpClientHandler();

            handler.Credentials = new NetworkCredential(username, password);
            handler.AllowAutoRedirect = false;
            handler.CookieContainer = cookies;
            handler.UseCookies = true;
            client = new HttpClient(handler);
            client.MaxResponseContentBufferSize = 9999999;
            client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
            client.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
            client.DefaultRequestHeaders.ExpectContinue = false;
        }
        return client;
    }
}
public String GetSAML()
{    
    if (client != null)
    {
        client = null;
    }
    String text = "";
    String SAMLTokenBase64String="";
    String urlRelayParty = "Your_Relay_party_identifier";
    string url = String.Format("{0}?loginToRp={1}", "https://***yourdomainforstsoradfs*****.com/adfs/ls/IdpInitiatedSignOn.aspx", HttpUtility.UrlEncode(urlRelayParty));
    do
    {
        result = Client.GetAsync(url).GetAwaiter().GetResult();
        text = result.Content.ReadAsStringAsync().GetAwaiter().GetResult();
        IEnumerable<string> values;
        if (result.Headers.TryGetValues("location", out values))
        {
            foreach (string s in values)
            {
                if (s.StartsWith("/"))
                {
                    url = url.Substring(0, url.IndexOf("/adfs/ls")) + s;
                }
                else
                    url = s;
            }
        }
        else
        {
            url = "";
        }
    }
    while (!String.IsNullOrEmpty(url));

    Regex reg = new Regex("SAMLResponse\\W+value\\=\\\"([^\\\"]+)\\\"");
    MatchCollection matches = reg.Matches(text);
    foreach (Match m in matches)
    {
        SAMLTokenBase64String = m.Groups[1].Value;
    }

    if (SAMLTokenBase64String != null && SAMLTokenBase64String.Trim().Length > 0)
    {
        SB("STS Login Successfull for " + urlRelayParty);
        return SAMLTokenBase64String;
    }
    

    SB("STS Login Failed for " + urlRelayParty);
    return "";
}
© www.soinside.com 2019 - 2024. All rights reserved.