如何为 IdP Saml2 响应添加自定义声明类型的属性

How to add attributes for custom claims types for IdP Saml2 response

我为我的 WebForms 项目转换了 IdPInitiatedController 示例代码。虽然我没有遇到编译器或运行时错误,但我似乎仍然无法在设置声明身份后将手动创建的声明添加到 Saml2AuthnResponse 对象。还有另一种方法可以将属性添加到 SAML 响应吗?该应用程序使用表单身份验证;并且凭据在 SQL 数据库中。这就是为什么我没有 Windows 身份。

' SSO CODE BEHIND
...
 Dim binding = New Saml2PostBinding With {
                    .RelayState = String.Format("RPID={0}", Uri.EscapeDataString(serviceProviderRealm))
                }
               
 Dim config = New Saml2Configuration With {
     .Issuer = "company.stage.app",
     .SingleSignOnDestination = New Uri(ConfigurationManager.AppSettings.Get("appValue")),
     .SigningCertificate = CertificateUtil.Load(X509Certificates.StoreName.TrustedPeople, X509Certificates.StoreLocation.LocalMachine, X509Certificates.X509FindType.FindByThumbprint, ConfigurationManager.AppSettings.Get("ThatKey")),
     .SignatureAlgorithm = Saml2SecurityAlgorithms.RsaSha256Signature
    }

Dim samlResponse = New Saml2AuthnResponse(config) With {
       .Status = Saml2StatusCodes.Success
      }

_ssoService.AddAttributes(samlResponse, currentUser)

binding.Bind(samlResponse)  ' NO ATTRIBUTES WERE ADDED

Me.SAMLResponse.Value = binding.XmlDocument.InnerXml
Me.RelayState.Value = binding.RelayState

frmSSO.Action = config.SingleSignOnDestination.AbsoluteUri()
frmSSO.Method = "POST"
Public Sub AddAttributes(ByRef samlResponse As Saml2AuthnResponse, ByVal currentUser As CurrentUser)
            Dim acctContact As CoveredInsuredDto = _coveragesService.GetAccountPointOfContact(currentUser.getControlNo())

            If Not IsNothing(acctContact) Then
                ' Adding Attributes as claims
                Dim claimIdentity = New ClaimsIdentity(Me.BuildClaims(currentUser, acctContact))

                samlResponse.NameId = New IdentityModel.Tokens.Saml2NameIdentifier(acctContact.Name)
                samlResponse.ClaimsIdentity = claimIdentity
            End If
        End Sub

Private Function BuildClaims(ByVal currentUser As CurrentUser, ByVal acctContact As CoveredInsuredDto) As IEnumerable(Of Claim)
            Dim claims = New List(Of Claim)

            If Not IsNothing(acctContact) Then               
                claims.Add(New Claim("FIRST_NAME", acctContact.FirstName))
                claims.Add(New Claim("LAST_NAME", acctContact.LastName))
            End If

            Return claims.ToList()
        End Function

问题是您忘记了 var token = response.CreateSecurityToken(appliesToAddress); 行,它实际上是创建令牌的行。

ASP.NET核心IdP Initiated sample code:

public IActionResult Initiate()
{
    var serviceProviderRealm = "https://some-domain.com/some-service-provider";

    var binding = new Saml2PostBinding();
    binding.RelayState = $"RPID={Uri.EscapeDataString(serviceProviderRealm)}";

    var config = new Saml2Configuration();

    config.Issuer = "http://some-domain.com/this-application";
    config.SingleSignOnDestination = new Uri("https://test-adfs.itfoxtec.com/adfs/ls/");
    config.SigningCertificate = CertificateUtil.Load(Startup.AppEnvironment.MapToPhysicalFilePath("itfoxtec.identity.saml2.testwebappcore_Certificate.pfx"), "!QAZ2wsx");
    config.SignatureAlgorithm = Saml2SecurityAlgorithms.RsaSha256Signature;

    var appliesToAddress = "https://test-adfs.itfoxtec.com/adfs/services/trust";

    var response = new Saml2AuthnResponse(config);
    response.Status = Saml2StatusCodes.Success;    

    var claimsIdentity = new ClaimsIdentity(CreateClaims());
    response.NameId = new Saml2NameIdentifier(claimsIdentity.Claims.Where(c => c.Type == ClaimTypes.NameIdentifier).Select(c => c.Value).Single(), NameIdentifierFormats.Persistent);
    response.ClaimsIdentity = claimsIdentity;
    var token = response.CreateSecurityToken(appliesToAddress);

    return binding.Bind(response).ToActionResult();
}

private IEnumerable<Claim> CreateClaims()
{
    yield return new Claim(ClaimTypes.NameIdentifier, "some-user-identity");
    yield return new Claim(ClaimTypes.Email, "some-user@domain.com");
}