【问题标题】:ASP.Net Core - Turn SAML assertion into ClaimsPrincipalASP.Net Core - 将 SAML 断言转换为 ClaimsPrincipal
【发布时间】:2017-07-28 10:18:49
【问题描述】:

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    我已经使用 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 中解析它 获得令牌后,您可以像这样获得用户凭据

      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;
            }
    

    要获得安全令牌的用户,您可以这样做

     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;
        }
    

    【讨论】:

    • System.IdentityModel 在.net core 中尚不支持
    • 我认为你应该手动解析 SAML 断言以校准原则
    【解决方案2】:

    http://blog.scottlogic.com/2015/11/19/oauth2-with-saml2.html

    这个 scott 的博客已经用简单的方式解释了它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-12
      • 2021-12-25
      • 2011-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-02
      • 2019-08-16
      相关资源
      最近更新 更多