I have a serialized SOAP request message with a SAML token holder-of-key that works against a vendor service. I want to create a demonstration program in C# to produce a similar request. To do this, I want to write a client that creates its own SAML token.
I've got a SAML2 token created successfully from a self signed cert and I am able to associate it to the request using the ChannelFactoryOperations.CreateChannelWithIssuedToken approach (.Net 4.0). Everything is working great but I can't figure out the C# required to place the signature after the assertion and use the SAML token as the signature KeyIdentifier to sign the timestamp. I'm not even sure what I am asking, but it seems like the signature after the token itself should be the easy part. But, the only way I've gotten the SAML to come out in the request is by declaring it of type BearerKey. But BearerKey appears to omit the signature after the Assertion. It seems I want SymmetricKey, but the token "has no keys." How do I make a signature element like this appear after the Assertion?
Here URI="#_1" is referring to the WS-Security timestamp (not shown) above.
Hi folks I can't believe I finally figured all of this out. This code loads up a self signed cert, generates a SAML token and then endorses the message with the SAML token. The problem I was having was with the "token has no keys" error. That was solved by creating an issuerToken and a key and passing that in to the token constructor. See below. I think the most helpful information I found online is this great post here http://devproconnections.com/development/generating-saml-tokens-wif-part-2
X509Certificate2 cert = new X509Certificate2("C:\\Users\\foobar\\desktop\\test.pfx", "test", X509KeyStorageFlags.MachineKeySet);
RSACryptoServiceProvider rsa = cert.PrivateKey as RSACryptoServiceProvider;
RsaSecurityKey rsaKey = new RsaSecurityKey(rsa);
RsaKeyIdentifierClause rsaClause = new RsaKeyIdentifierClause(rsa);
SecurityKeyIdentifier signingSki = new SecurityKeyIdentifier(new SecurityKeyIdentifierClause[] { rsaClause });
SigningCredentials signingCredentials = new SigningCredentials(rsaKey, SecurityAlgorithms.RsaSha1Signature, SecurityAlgorithms.Sha1Digest, signingSki);
Saml2NameIdentifier saml2NameIdentifier = new Saml2NameIdentifier("C=US,O=hi mom,CN=test", new System.Uri("urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName"));
Saml2Assertion saml2Assertion2 = new Saml2Assertion(saml2NameIdentifier);
saml2Assertion2.SigningCredentials = signingCredentials;
Saml2Subject saml2Subject = new Saml2Subject();
saml2NameIdentifier = new Saml2NameIdentifier("foo@bar.edu", new System.Uri("urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName"));
saml2Subject.NameId = saml2NameIdentifier;
Saml2SubjectConfirmationData subjectConfirmationData = new Saml2SubjectConfirmationData();
Saml2SubjectConfirmation subjectConfirmation = new Saml2SubjectConfirmation(new Uri("urn:oasis:names:tc:SAML:2.0:cm:holder-of-key"));
subjectConfirmation.SubjectConfirmationData = subjectConfirmationData;
subjectConfirmationData.KeyIdentifiers.Add(signingSki);
saml2Subject.SubjectConfirmations.Add(subjectConfirmation);
saml2Assertion2.Subject = saml2Subject;
Saml2AuthenticationContext saml2AuthCtxt = new Saml2AuthenticationContext(new Uri("urn:oasis:names:tc:SAML:2.0:ac:classes:X509"));
Saml2AuthenticationStatement saml2AuthStatement = new Saml2AuthenticationStatement(saml2AuthCtxt);
saml2AuthStatement.SessionIndex = "123456";
saml2Assertion2.Statements.Add(saml2AuthStatement);
Saml2AttributeStatement saml2AttStatement = new Saml2AttributeStatement();
Saml2Attribute saml2Attribute = new Saml2Attribute("urn:oasis:names:tc:xspa:1.0:subject:subject-id", "foo bar test");
saml2AttStatement.Attributes.Add(saml2Attribute);
saml2Attribute = new Saml2Attribute("urn:oasis:names:tc:xspa:1.0:subject:organization", "urn:oid:"+senderOid);
saml2AttStatement.Attributes.Add(saml2Attribute);
saml2Attribute = new Saml2Attribute("urn:oasis:names:tc:xspa:1.0:subject:organization-id", "urn:oid:" + senderOid);
saml2AttStatement.Attributes.Add(saml2Attribute);
saml2Attribute = new Saml2Attribute("urn:nhin:names:saml:homeCommunityId", "urn:oid:" + senderOid);
saml2AttStatement.Attributes.Add(saml2Attribute);
saml2Attribute = new Saml2Attribute("urn:oasis:names:tc:xacml:2.0:subject:role");
saml2AttStatement.Attributes.Add(saml2Attribute);
saml2Assertion2.Statements.Add(saml2AttStatement);
List<SecurityKey> keyList = new List<SecurityKey>();
keyList.Add(rsaKey);
ReadOnlyCollection<SecurityKey> keys = new ReadOnlyCollection<SecurityKey>(keyList);
X509SecurityToken issuerToken = new X509SecurityToken(cert);
Saml2SecurityToken token2 = new Saml2SecurityToken(saml2Assertion2,keys,issuerToken);
XcpdRespondingGatewaySyncService.RespondingGatewaySyncClient myClient = new XcpdRespondingGatewaySyncService.RespondingGatewaySyncClient("IRespondingGatewaySync2");
CustomBinding customBinding = myClient.Endpoint.Binding as CustomBinding;
SecurityBindingElement element = customBinding.Elements.Find<SecurityBindingElement>();
IssuedSecurityTokenParameters tokenParameters = element.EndpointSupportingTokenParameters.Signed[0].Clone() as IssuedSecurityTokenParameters;
tokenParameters.TokenType = System.IdentityModel.Tokens.SecurityTokenTypes.Saml;
tokenParameters.RequireDerivedKeys = false;
tokenParameters.KeyType = SecurityKeyType.SymmetricKey;
element.EndpointSupportingTokenParameters.Signed.Clear();
element.EndpointSupportingTokenParameters.Endorsing.Add(tokenParameters);
myClient.ChannelFactory.Credentials.SupportInteractive = false;
myClient.ChannelFactory.ConfigureChannelFactory();
XcpdRespondingGatewaySyncService.IRespondingGatewaySync myChannel = ChannelFactoryOperations.CreateChannelWithIssuedToken(myClient.ChannelFactory, token2);
来源:https://stackoverflow.com/questions/22951121/need-signature-after-saml-token-in-client-request