c# - ASP.Net Core - 将 SAML 断言转换为 ClaimsPrincipal

标签 c# asp.net-core saml saml-2.0 kentor-authservices

有一个 question about using SAML in ASP.Net Core ,但我需要额外的帮助。

那里唯一的答案提到了 Kentor.AuthServices,但我不明白如何使用它。我在这个或其他 SAML 库、文档、博客文章和示例应用程序中找到的所有内容都是关于联系某些外部身份验证服务以及处理登录和注销的。

但我不需要这些。我正在使用的设置在面向边缘的防火墙应用程序中执行此操作,并且登录/注销请求永远不会到达我的应用程序。我得到的只是 cookie 中的 SAML token ,我需要对其进行验证并将其转换为 ClaimsPrincipal。我不能(部署网络设置非常偏执)并且不想联系任何身份提供商。

目前我已经编写了一个中间件,它获取 cookie,解析它,并解析出声明主体所需的部分。但我不做任何验证,无论是 XML 签名还是 SAML 有效性(有效时间属性等)。使用 .Net Core 2.0 Preview 2 我可以进行 XML 签名验证,但我仍然坚持进行 SAML 验证。是否有一个库只验证 SAML 约束而不做任何其他事情(或者,至少,我可以忽略其他一切)?我相信 Kentor 或 ITfoxtec 或 elerch 的 SAML2.Core 必须包含这样的功能,但我不知道它在哪里。

最佳答案

我已经使用 System.IdentityModel.Tokens 中的 SecurityTokenHandlerCollection 类完成了此操作 我希望这段代码对您有所帮助。

 public Saml2SecurityToken DeserializeSAMLResponse(string samlResponse)
    {
        //Deserializing saml response

        Saml2SecurityToken token;
        using (var reader = XmlReader.Create(new StringReader(samlResponse)))
        {
            reader.ReadToFollowing("Assertion", Infrastructure.Enumerations.StringEnum.GetStringValue(SAMLProtocoles.SAML_20_ASSERTION));
            // Deserialize the token so that data can be taken from it and plugged into the RSTR
            SecurityTokenHandlerCollection tokenHandlerCollection = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();
            token = (Saml2SecurityToken)tokenHandlerCollection.ReadToken(reader.ReadSubtree());
        }

        //Deserializing successful
        return token;
    }

它将在内部验证 SAML 并在 Saml2SecurityToken 中解析它 获得 token 后,您可以像这样使用用户凭据

  public User ReadSamlResponse(string samlResponse, string profileName, bool isSAMLProfile = true)
    {
        User User = new User();
        var DecodedSamlResponse = Convert.FromBase64String(samlResponse);
        string ResponseDecoded = coding.UTF8.GetString(DecodedSamlResponse);

            Saml2SecurityToken Token = _samlAuthenticationService.DeserializeSAMLResponse(ResponseDecoded);
            if ()// apply condition here if you need to validate signature
            {
                if (!_samlAuthenticationService.ValidateSamlToken(ResponseDecoded, AuthenticationConnector, isSAMLProfile))
                    throw new Exception("Signature is invalid");
            }

            User = GetUserFromToken(Token);
            return User;
        }

要获取安全 token 的用户,您可以这样做

 public User GetUserFromToken(Saml2SecurityToken Token)
    {
        //Get user information from the token started
        User User = new User();
        if (Token != null)
        {
            if (Token.Assertion.Subject.NameId != null && (Token.Assertion.Subject.NameId.Format == null || Token.Assertion.Subject.NameId.Format.OriginalString == "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"))
                User.EmailAddress = Token.Assertion.Subject.NameId.Value;
            foreach (var Statement in Token.Assertion.Statements)
            {
                var AttributeStatement = Statement as Saml2AttributeStatement;
                var AuthenticationStatement = Statement as Saml2AuthenticationStatement;
                if (AttributeStatement != null)
                    foreach (var Saml2Attribute in AttributeStatement.Attributes)
                    {
                        if (Saml2Attribute.Name.Equals("mail") || Saml2Attribute.Name.Equals("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"))
                            User.EmailAddress = Saml2Attribute.Values[0];
                        if (Saml2Attribute.Name.Equals("uid") || Saml2Attribute.Name.Equals("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"))
                            User.Name = Saml2Attribute.Values[0];
                        if (Saml2Attribute.Name.Equals("phone"))
                            User.MobileNumber = Saml2Attribute.Values[0];
                        if (Saml2Attribute.Name.Equals("title"))
                            User.JobTitle = Saml2Attribute.Values[0];
                        if (Saml2Attribute.Name.Equals("company"))
                            User.CompanyName = Saml2Attribute.Values[0];
                    }
                if (AuthenticationStatement != null)
                {
                    User.SAMLSessionIndex = AuthenticationStatement.SessionIndex;
                }
            }
        }
        //Successfully parsed user credentials
        return User;
    }

关于c# - ASP.Net Core - 将 SAML 断言转换为 ClaimsPrincipal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45370886/

相关文章:

c# - 将 C# COM 对象数组传递给 VB6

c# - 通过 POST、PUT 方法返回 400 Bad Request,但 GET 工作正常

c# - 等待所有线程完成,超时

c# - 获取连接属性尚未设置错误

c# - 是否可以在 .net 程序中使用 TOR 网络?

c# - 在 Visual Studio 2017 中单击 ASP.NET Core 2.0 项目的“发布”不会执行任何操作

html - Razor Pages 中的表单操作标记帮助程序不会重定向我

single-sign-on - Windows Identity Foundation 不正式支持 SAML 2.0;使用 WIF CTP 还是坚持使用 SAML 1.1?

java - 需要有关 SAML 2.0 的信息

saml - SAML 如何真正提供安全性?