问题
I attempt the following:
- A WCF client calls a STS and gets SAML assertion
- The client calls a service using the SAML assertion
Now I have implemented the scenario above as three LinqPad scripts: client.linq
, sts.linq
(self hosted WCF service) and service.linq
(self hosted WCF service). They can all be found at https://github.com/codeape2/WCF_STS
I need some help getting this to work.
Using the following code in client.linq
, I am able to call my STS and get a SAML assertion:
SecurityToken GetToken()
{
var binding = new BasicHttpBinding();
var factory = new WSTrustChannelFactory(binding, stsAddress);
factory.TrustVersion = TrustVersion.WSTrustFeb2005;
var rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Symmetric,
AppliesTo = new EndpointReference(serviceAddress)
};
return factory.CreateChannel().Issue(rst);
}
Next step, I use the following code to (attempt to) call my service with the SAML assertion included:
var binding = new WSFederationHttpBinding(WSFederationHttpSecurityMode.Message);
binding.Security.Message.EstablishSecurityContext = false;
var factory = new ChannelFactory<ICrossGatewayQueryITI38>(
binding,
new EndpointAddress(new Uri(serviceAddress), new DnsEndpointIdentity("LocalSTS"))
);
factory.Credentials.SupportInteractive = false;
factory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode =
X509CertificateValidationMode.None;
var proxy = factory.CreateChannelWithIssuedToken(token);
var response = proxy.CrossGatewayQuery(
Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "urn:ihe:iti:2007:CrossGatewayQuery", "Hello world")
);
What happens next I totally do not understand. I have fiddler running when I run the script, and here's what I see:
- The first request to
/STS
(as expected) The
proxy.CrossGatewayQuery
results in three calls to/Service
:2.1. A SOAP call with action
http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue
2.2. A SOAP call with action
http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue
2.3. A final SOAP call with action
urn:ihe:iti:2007:CrossGatewayQuery
. Using Fiddler, I notice that the SOAP security header includes the SAML assertion from step one.
The final call results in a SOAP fault back from the service: At least one security token in the message could not be validated. The saved Fiddler request/response log is here: https://drive.google.com/file/d/0B-UZlLvBjjB2S050TXRhVEo2Vmc/view?usp=sharing
If anyone could enlighten me regarding the following, I would be very grateful:
- Why does the WCF client send the
RST/Issue
andRSTS/Issue
requests to the/Service
(steps 2.1 and 2.2 above) ? - How can I configure the pieces to do what I want, i.e. send one request to the STS and then one request to the service, passing the SAML assertion I got from the STS.
回答1:
The first problem was with re negotiating of service credentials.
This change took care of that:
binding.Security.Message.NegotiateServiceCredential = false
Then the service had to enable WIF configuration:
host.Credentials.UseIdentityConfiguration = true;
host.Credentials.IdentityConfiguration = CreateIdentityConfig();
IdentityConfiguration CreateIdentityConfig()
{
IdentityConfiguration identityConfig = new IdentityConfiguration(false);
//AUDIENCE URI
//the token we receive contains this value, so if do not match we fail
identityConfig.AudienceRestriction.AllowedAudienceUris.Add(new Uri($"http://{Environment.MachineName}:8000/Service"));
//ISSUER NAME REGISTRY explicit the thumbprint of the accepted certificates, if the token coming in is not signed with any of these certificates then is considered invalid
var issuerNameRegistry = new ConfigurationBasedIssuerNameRegistry();
issuerNameRegistry.AddTrustedIssuer("81 5b 06 b2 7f 5b 26 30 47 3b 8a b9 56 bb 9f 9f 8c 36 20 76", "signing certificate sts"); //STS signing certificate thumbprint
identityConfig.IssuerNameRegistry = issuerNameRegistry;
identityConfig.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
return identityConfig;
}
There were other changes too, the github repo has updated code that works in the master
branch.
Thanks to MS support who walked me through figuring this out.
来源:https://stackoverflow.com/questions/42342062/call-wcf-service-with-issued-token