I'm using ACS/Service Identities as a temporary STS while I get things into place. Unfortunately, while I appear to be able to get a SAML 1.1 token fine from ACS, the second I try to pass it into my WCF service things go crazy. As far as I can tell, the token isn't expired (it's being used promptly), I'm not sure how it could be invalid, and nothing I've done with logging has displayed to me any detail on what exactly could be wrong. I'm tempted to assign blame to the binding, because I've never done a formal WCF/WIF binding before. Can anyone see anything wrong with the client/server bindings I'm using (the client was generated via service reference), or suggest an alterative avenue of investigation?
BTW, both the server and client are running on the same development machine.
Web.config:
<configuration>
<configSections>
<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
</configSections>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
<add key="ida:FederationMetadataLocation" value="--omitted--" />
<add key="ida:ProviderSelection" value="productionSTS" />
</appSettings>
<location path="FederationMetadata">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
<system.web>
<compilation debug="true" targetFramework="4.5">
<assemblies>
<add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</assemblies>
</compilation>
<httpRuntime targetFramework="4.5" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceCredentials useIdentityConfiguration="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add scheme="https" binding="ws2007FederationHttpBinding" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<bindings>
<ws2007FederationHttpBinding>
<binding name="">
<security mode="TransportWithMessageCredential">
<message issuedKeyType="BearerKey" issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"/>
</security>
</binding>
</ws2007FederationHttpBinding>
</bindings>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true" />
</system.webServer>
<system.identityModel>
<identityConfiguration>
<audienceUris>
<add value="https://localhost:44300/Service1.svc" />
</audienceUris>
<issuerNameRegistry>
<trustedIssuers>
<add name="--omitted--" thumbprint="--omitted--"/>
</trustedIssuers>
</issuerNameRegistry>
<certificateValidation certificateValidationMode="None"/>
</identityConfiguration>
</system.identityModel>
</configuration>
App.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1" />
</basicHttpBinding>
<ws2007FederationHttpBinding>
<binding name="WS2007FederationHttpBinding_IService1">
<security mode="TransportWithMessageCredential">
<message issuedKeyType="BearerKey" issuedTokenType="">
<tokenRequestParameters>
<trust:SecondaryParameters xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<trust:TokenType xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</trust:TokenType>
<trust:KeyType xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</trust:KeyType>
<trust:CanonicalizationAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/10/xml-exc-c14n#</trust:CanonicalizationAlgorithm>
<trust:EncryptionAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptionAlgorithm>
</trust:SecondaryParameters>
</tokenRequestParameters>
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:51853/Service1.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
name="BasicHttpBinding_IService1" />
<endpoint address="https://localhost:44300/Service1.svc" binding="ws2007FederationHttpBinding"
bindingConfiguration="WS2007FederationHttpBinding_IService1"
contract="ServiceReference1.IService1" name="WS2007FederationHttpBinding_IService1" />
</client>
</system.serviceModel>
Client code:
static void Main(string[] args)
{
var factory = new WSTrustChannelFactory(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), new EndpointAddress("--Azure ACS URL omitted--"));
factory.TrustVersion = TrustVersion.WSTrust13;
factory.Credentials.UserName.UserName = "--omitted--";
factory.Credentials.UserName.Password = "--omitted--";
var rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Bearer,
AppliesTo = new EndpointReference("https://localhost:44300/Service1.svc")
};
SecurityToken token = factory.CreateChannel().Issue(rst);
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;
binding.Security.Message.EstablishSecurityContext = false;
var factory2 = new ChannelFactory<IService1>(binding, new EndpointAddress("https://localhost:44300/Service1.svc"));
factory2.Credentials.SupportInteractive = false;
factory2.Credentials.UseIdentityConfiguration = true;
var proxy = factory2.CreateChannelWithIssuedToken(token);
var info = proxy.GetData("testing"); // Exception thrown here
}
Exception:
System.ServiceModel.Security.MessageSecurityException was unhandled
HResult=-2146233087
Message=An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.
Source=mscorlib
StackTrace:
Server stack trace:
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at TestWCFClient.ServiceReference1.IService1.GetData(String value)
at TestWCFClient.Program.Main(String[] args) in c:\Users\nicole\Documents\Visual Studio 2012\Projects\TestWCFClient\Program.cs:line 43
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException: System.ServiceModel.FaultException
HResult=-2146233087
Message=The message could not be processed. This is most likely because the action 'http://tempuri.org/IService1/GetData' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings. The security context token would be invalid if the service aborted the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase the Receive timeout on the service endpoint's binding.
InnerException:
ETA:
In addition, I've tried: switching to SAML 2.0, switching to JWT with the preview JWT token handler, changing the receive timeout, switching the host machine time to UTC, syncing the host with the Windows Time Service explicitly, and waiting for five minutes after the token is issued before using it.
The MessageSecurityException was right: it's a binding error.
I was mixing a couple of code samples together and got bitten by the mismatch. EstablishSecurityContext is not just window dressing, it is a real part of the binding, and the values must match between service and client.
My application code reads:
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;
binding.Security.Message.EstablishSecurityContext = false; // this line is the problem
The service binding is:
<bindings>
<ws2007FederationHttpBinding>
<binding name="">
<security mode="TransportWithMessageCredential">
<message issuedKeyType="BearerKey" issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"/> <!-- this line does not match -->
</security>
</binding>
</ws2007FederationHttpBinding>
</bindings>
The service binding should be:
<bindings>
<ws2007FederationHttpBinding>
<binding name="">
<security mode="TransportWithMessageCredential">
<message issuedKeyType="BearerKey" establishSecurityContext="false"/>
</security>
</binding>
</ws2007FederationHttpBinding>
</bindings>
And presto, it works.
Related
I have a WCF Service that works when i run it at localhost, using the WCF Test Client I can invoke it and get a result. I can also see it when I actually host it on the live server as it generates the methods on the test client and I can see the wsdl page when opened in Chrome.
But (because it always has a but) when I invoke it with WCF Test Client I get this error:
Failed to invoke the service. Possible causes: The service is offline or inaccessible; the client-side configuration does not match the proxy; the existing proxy is invalid. Refer to the stack trace for more detail. You can try to recover by starting a new proxy, restoring to default configuration, or refreshing the service.
Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at IRp3Services.CreateTransaction(NewTransaction model) at Rp3ServicesClient.CreateTransaction(NewTransaction model)
I cant seem to understand why, I have tested it locally and works perfectly, here is the web config:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ConsultasSoap" />
<binding name="TransaccionesSoap" />
<binding name="SeguridadSoap" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://address/Rp3.Web.Credishop.Afiliados/consultas.asmx"
binding="basicHttpBinding" bindingConfiguration="ConsultasSoap"
contract="RP3Consultas.ConsultasSoap" name="ConsultasSoap" />
<endpoint address="http://address/Rp3.Web.Credishop.Afiliados/transacciones.asmx"
binding="basicHttpBinding" bindingConfiguration="TransaccionesSoap"
contract="RP3Transacciones.TransaccionesSoap" name="TransaccionesSoap" />
<endpoint address="http://address/Rp3.Web.Credishop.Afiliados/seguridad.asmx"
binding="basicHttpBinding" bindingConfiguration="SeguridadSoap"
contract="RP3Seguridad.SeguridadSoap" name="SeguridadSoap" />
</client>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpBinding" scheme="http" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
I am really at a loss here, I would love any input on what I am doing wrong here.
I get the error "{"The remote server returned an error: (403) Forbidden."} The HTTP request was forbidden with client authentication scheme 'Anonymous'." when using basicHttpBinding with Transport security and certificate credential. My service is in amazon ec2 instance and my client app remotely connect to it over the internet. I am able to connect to the wcf service if my Transport credential is set to "None" in both the web.config of the service and app.config of the client. My service certificate is like "www.example.com" is installed on amazon ec2 "local machine store" and "Personal Folder". My client app certificate is just a self-signed certificate which I installed to its "local machine and Personal Folder" and also to the "Trusted People store" in the amazon ec2 instance where my wcf service is. I have also setup "https" to my IIS site bindings and I can reach the site through like "https://www.example.com"
Below is the web.config, app.config, and the code I have on the client app.
Service Web.config:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBinding_Config" >
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="MyProject.MyService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttpBinding_Config"
contract="MyService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerOrChainTrust" trustedStoreLocation="LocalMachine"/>
</clientCertificate>
<serviceCertificate findValue="www.example.com" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Client app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBinding_Config" >
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://www.example.com/sub/Service1.svc"
binding="basicHttpBinding" bindingConfiguration="basicHttpBinding_Config"
contract="ServiceReference1.MyService" name="BasicHttpBinding_MyService" />
</client>
<behaviors>
<endpointBehaviors>
<behavior>
<clientCredentials>
<clientCertificate findValue="clientKey"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Client App Console Code:
static void Main(string[] args)
{
System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };
ServiceReference1.MyServiceClient client = new ServiceReference1.MyServiceClient();
string[] a = client.GetMethods(ref mh);
foreach (string s in a)
{
Console.WriteLine(s);
}
Console.ReadKey();
}
The Diagnostic Tracing returns below:
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>131077</EventID>
<Type>3</Type>
<SubType Name="Critical">0</SubType>
<Level>1</Level>
<TimeCreated SystemTime="2018-11-16T21:50:58.8220239Z" />
<Source Name="System.ServiceModel" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessName="ConsoleApplication1" ProcessID="22220" ThreadID="1" />
<Channel />
<Computer>DESKTOP-RPNI11M</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical">
<TraceIdentifier>UnhandledException</TraceIdentifier>
<Description>Unhandled exception</Description>
<AppDomain>ConsoleApplication1.exe</AppDomain>
<Exception>
<ExceptionType>System.ServiceModel.Security.MessageSecurityException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The HTTP request was forbidden with client authentication scheme 'Anonymous'.</Message>
<StackTrace>
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest request, HttpWebResponse response, WebException responseException, HttpChannelFactory`1 factory)
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory`1 factory, WebException responseException, ChannelBinding channelBinding)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at ConsoleApplication1.ServiceReference1.IOD_V416.GetMethods(GetMethodsRequest request)
at ConsoleApplication1.ServiceReference1.OD_V416Client.ConsoleApplication1.ServiceReference1.IOD_V416.GetMethods(GetMethodsRequest request) in D:\Workfolder\Projects2\MyProject\WCF_App\MyService - Copy (3)\ConsoleApplication1\Service References\ServiceReference1\Reference.cs:line 72017
at ConsoleApplication1.ServiceReference1.OD_V416Client.GetMethods(MultiSpeakMsgHeader& MultiSpeakMsgHeader) in D:\Workfolder\Projects2\MyProject\WCF_App\MyService - Copy (3)\ConsoleApplication1\Service References\ServiceReference1\Reference.cs:line 72023
at ConsoleApplication1.Program.Main(String[] args) in D:\Workfolder\Projects2\MyProject\WCF_App\MyService - Copy (3)\ConsoleApplication1\Program.cs:line 43
</StackTrace>
<ExceptionString>System.ServiceModel.Security.MessageSecurityException: The HTTP request was forbidden with client authentication scheme 'Anonymous'. ---> System.Net.WebException: The remote server returned an error: (403) Forbidden.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
--- End of inner exception stack trace ---
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest request, HttpWebResponse response, WebException responseException, HttpChannelFactory`1 factory)
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory`1 factory, WebException responseException, ChannelBinding channelBinding)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at ConsoleApplication1.ServiceReference1.IOD_V416.GetMethods(GetMethodsRequest request)
at ConsoleApplication1.ServiceReference1.OD_V416Client.ConsoleApplication1.ServiceReference1.IOD_V416.GetMethods(GetMethodsRequest request) in D:\Workfolder\Projects2\MyProject\WCF_App\MyService - Copy (3)\ConsoleApplication1\Service References\ServiceReference1\Reference.cs:line 72017
at ConsoleApplication1.ServiceReference1.OD_V416Client.GetMethods(MultiSpeakMsgHeader& MultiSpeakMsgHeader) in D:\Workfolder\Projects2\MyProject\WCF_App\MyService - Copy (3)\ConsoleApplication1\Service References\ServiceReference1\Reference.cs:line 72023
at ConsoleApplication1.Program.Main(String[] args) in D:\Workfolder\Projects2\MyProject\WCF_App\MyService - Copy (3)\ConsoleApplication1\Program.cs:line 43</ExceptionString>
<InnerException>
<ExceptionType>System.Net.WebException, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The remote server returned an error: (403) Forbidden.</Message>
<StackTrace>
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
</StackTrace>
<ExceptionString>System.Net.WebException: The remote server returned an error: (403) Forbidden.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)</ExceptionString>
</InnerException>
</Exception>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
I did look to other similar issues but none has solve it yet, I'm continuously searching for the right solutions, I appreciate any help or advice the community provides.
EDIT:
Probably better to use a sha2 cert:
makecert -len 2048 -r -a sha256 -sv private.pvk -n CN=yoursubjectname cert.cer
pvk2pfx -spc cert.cer -pvk private.pvk -pfx out.pfx
Install the private cert(.pfx) on the host, set in IIS app, and install the public cert on the client(.cer), you will have to install in both personal and trusted people stores.
EDIT: I think you also need to give your behavior a name in the host and client config and assign that behavior to your endpoints.
Host:
<behavior name="serviceBahavior">
<service name="MyProject.MyService" behaviorConfiguration="serviceBahavior">
Client:
<behavior name="clientBahavior">
<endpoint address="https://www.example.com/sub/Service1.svc"
binding="basicHttpBinding" bindingConfiguration="basicHttpBinding_Config"
contract="ServiceReference1.MyService" name="BasicHttpBinding_MyService" behaviorConfiguration="clientBahavior" />
I think since you are using <security mode="Transport"> you will need to make your mex as HTTPS:
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
Also set in your behavior the serviceMetadata
from:
<serviceMetadata httpGetEnabled="true"/>
to <serviceMetadata httpsGetEnabled="true"/>
Also, make sure your transport in the client config matches the host config:
<transport clientCredentialType="Certificate"/>
I found the following solution that works for this error I encountered.
First, I created a certificate as follows:
makecert -n "CN=MyRootSigningKey" -r -sv MyRootSigningKey.pvk MyRootSigningKey.cer
Second, I treat this as my root key and install it in my AWS service under the certificate store "Trusted Root Certification Authorities" using mmc.
Third, I created a self-signed cert using the root key "MyRootSigningKey" as follows:
makecert -sk MySignedKeyName -iv MyRootSigningKey.pvk -n "CN=MySignedKey" -ic MyRootSigningKey.cer -sr localmachine -ss my -sky exchange -pe
Last, I reference the self signed cert "MySignedKey" in my client app config like below:
<client>
<endpoint address="https://www.example.com/sub/Service1.svc" behaviorConfiguration="clientBehavior"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_MyService"
contract="ServiceReference1.MyService" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="clientBehavior">
<clientCredentials>
<clientCertificate findValue="MySignedKey"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
I have written a web service in wcf that returns a object. But When I call it from client code it does not return any object.
My class that object I want to return
[DataContract]
public class OrderData
{
[DataMember]
public List<ORDER_INFO> OrderInfoList { get; set; }
[DataMember]
public List<ORDER_PRODUCT_MAPPING> OrderProductMappingList { get; set; }
}
My Service Interface
[ServiceContract]
public interface ISyncService
{
[OperationContract]
OrderData InsertOrderData(decimal depotId);
}
Interface implementation class
public class SyncService : ISyncService
{
readonly InceptaDbContext _db = new InceptaDbContext();
public OrderData InsertOrderData(decimal depotId)
{
var orderData = new OrderData
{
OrderInfoList = new List<ORDER_INFO>(),
OrderProductMappingList = new List<ORDER_PRODUCT_MAPPING>()
};
var orderList = _db.ORDER_INFO
.Where(m => m.D_ID.Equals(depotId)&& m.STATUS.Equals("1"));
//.Where(m => m.STATUS.Equals("1"));
foreach (var orderInfo in orderList)
{
orderData.OrderInfoList.Add(orderInfo);
orderData.OrderProductMappingList.AddRange(
_db.ORDER_PRODUCT_MAPPING.Where(m => m.ORDER_ID.Equals
(orderInfo.ORDER_ID)));
}
foreach (var orderInfo in orderList)
{
orderInfo.STATUS = "2";
_db.Entry(orderInfo).State = EntityState.Modified;
}
_db.SaveChanges();
return orderData;
}
}
My server web Config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</assemblies>
</compilation>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="true" />
</system.webServer>
<connectionStrings>
<add name="InceptaDbContext"
connectionString="metadata=res://*/DbContext.Model1.csdl|res://*/DbContext.Model1.ssdl|res://*/DbContext.Model1.msl;provider=Oracle.DataAccess.Client;provider connection string="DATA SOURCE=localhost/InceptaMSFA;PASSWORD=bs23;PERSIST SECURITY INFO=True;USER ID=BS"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
My client app is console app in C#
main program
class Program
{
static void Main(string[] args)
{
var client = new SyncServiceClient();
var db = new InceptaDbContext();
var order = client.InsertOrderData(1.0m);
foreach (var s in order.OrderInfoList)
{
db.ORDER_INFO.Add(new ConsumeDataSyncService.DbContext.ORDER_INFO
{
ORDER_ID = s.ORDER_ID,
CH_ID = s.CH_ID,
D_ID = s.D_ID,
EMP_ID = s.EMP_ID,
ORDER_DATE = s.ORDER_DATE,
ORDER_TYPE = s.ORDER_TYPE,
PAY_OPTION = s.PAY_OPTION,
PRODUCT_COUNT = s.PRODUCT_COUNT,
STATUS = "2"
});
Console.WriteLine(s.ORDER_ID +"Inserted");
}
foreach (var s in order.OrderProductMappingList)
{
var orderProductMapping = new ConsumeDataSyncService.DbContext.ORDER_PRODUCT_MAPPING
{
ID = s.ID,
ORDER_ID = s.ORDER_ID,
P_CODE = s.P_CODE,
QUANTITY = s.QUANTITY
};
db.ORDER_PRODUCT_MAPPING.Add(orderProductMapping);
Console.WriteLine(s.ID + "Inserted");
}
db.SaveChanges();
Console.ReadKey();
}
}
and app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ISyncService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8092/SyncService.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISyncService" contract="OrderSyncService.ISyncService" name="BasicHttpBinding_ISyncService" />
</client>
</system.serviceModel>
<connectionStrings>
<add name="InceptaDbContext" connectionString="metadata=res://*/DbContext.Model1.csdl|res://*/DbContext.Model1.ssdl|res://*/DbContext.Model1.msl;provider=Oracle.DataAccess.Client;provider connection string="DATA SOURCE=192.168.1.159/Incepta;PASSWORD=bs23;USER ID=BS"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
the error I got at the time of debugging
Failed to invoke the service. Possible causes: The service is offline or inaccessible; the client-side configuration does not match the proxy; the existing proxy is invalid. Refer to the stack trace for more detail. You can try to recover by starting a new proxy, restoring to default configuration, or refreshing the service.
The underlying connection was closed: The connection was closed unexpectedly.
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at ISyncService.InsertOrderData(Decimal depotId)
at SyncServiceClient.InsertOrderData(Decimal depotId)
Inner Exception:
The underlying connection was closed: The connection was closed unexpectedly.
at System.Net.HttpWebRequest.GetResponse()`enter code here`
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
Usually with this error, there seems to be a circular reference in the model so it can't be serialized. Enable tracing to see the service's log, where you can see what exception caused the service to unexpectedly close the connection.
Thanks everybody who gave me time .... I have solved this problem. In the OrderData class there are two properties and that are also another class. So I have added the attributes like [DataContract] in the classes(ORDER_INFO and ORDER_PRODUCT_MAPPING) and [DataMember] in the properties and solved my problem.
Try with by adding
[Serializable,DataContract()]
in above the class name.
I have a WCF service that uses message security over HTTPS using wsHttpBinding behind load balancer. When connects to the service on web browser via https, it works. However, Windowns forms client failed, using certificate over https,
Update
The request url is https, but after the exception saying http, below is exception tracing on server side:
For example: the request url is
https://www.server.com/wcf.svc'.
But it becomes
http://www.server.com:81/wcf.svc' on the server side. Is it the load balancer causing it.
System.ServiceModel.EndpointNotFoundException, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
There was no channel actively listening at 'http://www.server.com:81/wcf.svc'. This is often caused by an incorrect address URI. Ensure that the address to which the message is sent matches an address on which a service is listening.
Below is the WCF service config:
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true"
logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="false" />
</diagnostics>
<services>
<service behaviorConfiguration="verServiceBehaviour" name="ver.Service">
<endpoint address="ver" binding="wsHttpBinding" bindingConfiguration="wshttpbindingcfg"
contract="ver.Iver" behaviorConfiguration ="verEndpointBehaviour">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="mexhttpbinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://www.server.com/" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<mexHttpBinding>
<binding name="mexhttpbinding" />
</mexHttpBinding>
<wsHttpBinding>
<binding name="wshttpbindingcfg" maxReceivedMessageSize="2000000000" sendTimeout="00:10:00">
<readerQuotas maxStringContentLength="2000000000"/>
<reliableSession ordered="true" enabled="false" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Certificate" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="verEndpointBehaviour">
<instanceContextBehavior/>
<verInspectorBehavior/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="verServiceBehaviour">
<dataContractSerializer maxItemsInObjectGraph="100000000"/>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerOrChainTrust" revocationMode="NoCheck" trustedStoreLocation="LocalMachine" mapClientCertificateToWindowsAccount="false"/>
</clientCertificate>
<serviceCertificate
x509FindType="FindByThumbprint"
findValue="xxxx"
storeLocation="LocalMachine"
storeName="My"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Below is client config:
<configuration>
<appSettings>
<add key="CertificateSubjectName" value="subjectName"/>
</appSettings>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ver.IverHTTPS" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Certificate" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://www.server.com/wcf.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ver.IverHTTPS"
contract="ServiceReference.verIver" name="verEndPoint" />
</client>
</system.serviceModel>
</configuration>
below is code in client using certificate:
var proxyClient = new ServiceReference.VerIVerClient("verEndPoint");
proxyClient.ClientCredentials.ClientCertificate.SetCertificate(
System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser,
System.Security.Cryptography.X509Certificates.StoreName.My,
System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectName,
subjectName");
proxyClient.CallService()
Below is exception received at client side:
System.ServiceModel.EndpointNotFoundException was unhandled
Message=There was no endpoint listening at https://ver20.server.com/wcf.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
Source=mscorlib
StackTrace:
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at verClient.ServiceReference.verIver.GetClaimver(GetClaimverClaimApplication ClaimApplication)
at verClient.ServiceReference.verIverClient.GetClaimver(GetClaimverClaimApplication ClaimApplication) in D:\Projects\ver\verClient\Service References\ServiceReference\Reference.cs:line 11330
at verClient.verForm.PostXmlTover(GetClaimverClaimApplication ClaimApplication) in D:\Projects\ver\verClient\verForm.cs:line 1408
at verClient.verForm.PostButton_Click(Object sender, EventArgs e) in D:\Projects\ver\verClient\verForm.cs:line 34
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at verClient.Program.Main() in D:\Projects\ver\verClient\Program.cs:line 18
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException: System.Net.WebException
Message=The remote server returned an error: (404) Not Found.
Source=System
StackTrace:
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
InnerException:
Review the configuration of your load balancer, and make sure that the requests are being for warded to the correct host AND PORT number. If the port number you chose is not standard, make sure to adjust the IIS Site Binding and the base address of your service.
One important thing to understand about transport security is that it has to be configured on a "hop" by "hop" basis. In your example, you have two hops (client) -> (load balancer) and (load balancer) -> (server).
Securing your connection from the client to the load balancer doesn't automatically configure security from the load balancer to the server. You need to install and configure an ssl certificate on both the load balancer and the server.
Your initial https request ended up being an http request on the server, that is a good indication that you did not configure a secure channel between the load balancer and the server.
If you do not wish to secure the connection between the load balancer and the server, then expose your service without transport security. With this, you can still have the communication from the client to the load balancer (the first hop) on ssl.
I’m having an issue using ADFS2 to secure a back-end WCF service that is being called from Passively Federated Website. I have the passive federation working on the website, but the back-end service is giving me problems.
The pieces of the puzzle.
Silverlight Client that is being served from Passively Federated Website.
The Silverlight calls a WCF service (App Service), hosted on the passively Federated Website.
I have SaveBootstrapToken set to true in the config.
From the App Service, I want to call a back-end WCF service using BootstrapToken with the ActAs scenarion.
Federated Website and Back-end WCF service are setup as separate RPs in the ADFS2, token encryption is turned on. Both are allowed to delegate.
Back-end Service configuration:
I have WIF incorporated into the pipeline using behavior extension.
<ws2007FederationHttpBinding>
<binding name="WS2007FederationHttpBinding_IQuoteService">
<security mode="TransportWithMessageCredential">
<message establishSecurityContext="false">
<issuer address="https://myADFSserver/adfs/services/trust/13/issuedtokenmixedsymmetricbasic256">
</issuer>
<issuerMetadata address="https://myADFSserver/adfs/services/trust/mex">
</issuerMetadata>
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
<behaviors>
<serviceBehaviors>
<behavior name="">
<federatedServiceHostConfiguration name="Service.QuoteService" />
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceCredentials>
<serviceCertificate findValue="000000000000000000000000000000" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Service.QuoteService">
<endpoint address="" binding="ws2007FederationHttpBinding" contract="Service.IQuoteService" bindingConfiguration="WS2007FederationHttpBinding_IQuoteService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
Client Configuration
When add the service using Add Service Reference tooling, the following config on the client gets created:
<customBinding>
<binding name="https://myADFSserver/adfs/services/trust/13/issuedtokenmixedsymmetricbasic256">
<security defaultAlgorithmSuite="Default" authenticationMode="IssuedTokenOverTransport"
requireDerivedKeys="false" securityHeaderLayout="Strict" includeTimestamp="true"
keyEntropyMode="CombinedEntropy" messageSecurityVersion="WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10">
<issuedTokenParameters keySize="256" keyType="SymmetricKey" tokenType="">
<additionalRequestParameters>
<trust:SecondaryParameters xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<trust:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey</trust:KeyType>
<trust:KeySize>256</trust:KeySize>
<trust:KeyWrapAlgorithm>http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p</trust:KeyWrapAlgorithm>
<trust:EncryptWith>http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptWith>
<trust:SignatureAlgorithm>http://www.w3.org/2000/09/xmldsig#hmac-sha1</trust:SignatureAlgorithm>
<trust:CanonicalizationAlgorithm>http://www.w3.org/2001/10/xml-exc-c14n#</trust:CanonicalizationAlgorithm>
<trust:EncryptionAlgorithm>http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptionAlgorithm>
</trust:SecondaryParameters>
</additionalRequestParameters>
</issuedTokenParameters>
<localClientSettings cacheCookies="true" detectReplays="false"
replayCacheSize="900000" maxClockSkew="00:05:00" maxCookieCachingTime="Infinite"
replayWindow="00:05:00" sessionKeyRenewalInterval="10:00:00"
sessionKeyRolloverInterval="00:05:00" reconnectTransportOnFailure="true"
timestampValidityDuration="00:05:00" cookieRenewalThresholdPercentage="60" />
<localServiceSettings detectReplays="false" issuedCookieLifetime="10:00:00"
maxStatefulNegotiations="128" replayCacheSize="900000" maxClockSkew="00:05:00"
negotiationTimeout="00:01:00" replayWindow="00:05:00" inactivityTimeout="00:02:00"
sessionKeyRenewalInterval="15:00:00" sessionKeyRolloverInterval="00:05:00"
reconnectTransportOnFailure="true" maxPendingSessions="128"
maxCachedCookies="1000" timestampValidityDuration="00:05:00" />
<secureConversationBootstrap />
</security>
<textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
messageVersion="Default" writeEncoding="utf-8">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</textMessageEncoding>
<httpsTransport manualAddressing="false" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous"
bypassProxyOnLocal="false" decompressionEnabled="true" hostNameComparisonMode="StrongWildcard"
keepAliveEnabled="true" maxBufferSize="65536" proxyAuthenticationScheme="Anonymous"
realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
useDefaultWebProxy="true" requireClientCertificate="false" />
</binding>
</customBinding>
<ws2007FederationHttpBinding>
<binding name="WS2007FederationHttpBinding_IQuoteService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text"
textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<message algorithmSuite="Default" issuedKeyType="SymmetricKey"
negotiateServiceCredential="true">
<issuer address="https://myADFSserver/adfs/services/trust/13/issuedtokenmixedsymmetricbasic256"
binding="customBinding" bindingConfiguration="https://myADFSserver/adfs/services/trust/13/issuedtokenmixedsymmetricbasic256" />
<issuerMetadata address="https://myADFSserver/adfs/services/trust/mex" />
<tokenRequestParameters>
<trust:SecondaryParameters xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<trust:KeyType xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey</trust:KeyType>
<trust:KeySize xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">256</trust:KeySize>
<trust:Claims Dialect="http://schemas.xmlsoap.org/ws/2005/05/identity"
xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<wsid:ClaimType Uri="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
Optional="true" xmlns:wsid="http://schemas.xmlsoap.org/ws/2005/05/identity" />
<wsid:ClaimType Uri="http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
Optional="true" xmlns:wsid="http://schemas.xmlsoap.org/ws/2005/05/identity" />
</trust:Claims>
<trust:KeyWrapAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p</trust:KeyWrapAlgorithm>
<trust:EncryptWith xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptWith>
<trust:SignWith xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2000/09/xmldsig#hmac-sha1</trust:SignWith>
<trust:CanonicalizationAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/10/xml-exc-c14n#</trust:CanonicalizationAlgorithm>
<trust:EncryptionAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptionAlgorithm>
</trust:SecondaryParameters>
</tokenRequestParameters>
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
<client>
<endpoint address="http://myServiceHost/Service/QuoteService.svc"
binding="ws2007FederationHttpBinding" bindingConfiguration="WS2007FederationHttpBinding_IQuoteService"
contract="QuoteService.IQuoteService" name="WS2007FederationHttpBinding_IQuoteService">
<identity>
<certificate encodedValue="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
</identity>
</endpoint>
</client>
Here's the Service Client Code:
List<Quote> quoteList = new List<Quote>();
ClaimsPrincipal myClaimsPrincipal = System.Web.HttpContext.Current.User as ClaimsPrincipal;
SecurityToken bootstrapToken = myClaimsPrincipal.Identities[0].BootstrapToken;
if (bootstrapToken == null)
{
throw new Exception("bootstrap tokein is null. Logout and try again.");
}
ChannelFactory<IQuoteServiceChannel> factory = new ChannelFactory<IQuoteServiceChannel>("WS2007FederationHttpBinding_IQuoteService");
factory.Credentials.SupportInteractive = false;
factory.Credentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "0000000000000000000000000000");
factory.ConfigureChannelFactory();
IQuoteServiceChannel channel;
//Create the channel with the bootstrap token
channel = factory.CreateChannelActingAs(bootstrapToken);
try
{
quoteList = channel.GetQuotes(quoteUser);
channel.Close();
}
catch (SecurityAccessDeniedException sadex)
{
channel.Abort();
throw;
}
catch (CommunicationException exception)
{
channel.Abort();
throw;
}
catch (TimeoutException timeoutEx)
{
channel.Abort();
throw;
}
catch (Exception ex)
{
channel.Abort();
throw;
}
return quoteList;
This is the exception I get:
System.ServiceModel.Security.SecurityNegotiationException was unhandled by user code
Message=SOAP security negotiation with 'https://myADFSserver/adfs/services/trust/13/issuedtokenmixedsymmetricbasic256' for target 'https://myADFSserver/adfs/services/trust/13/issuedtokenmixedsymmetricbasic256' failed. See inner exception for more details.
Source=mscorlib
StackTrace:
Server stack trace:
at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout)
at System.ServiceModel.Security.IssuanceTokenProviderBase`1.GetTokenCore(TimeSpan timeout)
at System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(TimeSpan timeout)
at Microsoft.IdentityModel.Protocols.WSTrust.FederatedSecurityTokenProvider.GetTokenCore(TimeSpan timeout)
at System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(TimeSpan timeout)
at System.ServiceModel.Security.SecurityProtocol.TryGetSupportingTokens(SecurityProtocolFactory factory, EndpointAddress target, Uri via, Message message, TimeSpan timeout, Boolean isBlockingCall, IList`1& supportingTokens)
at System.ServiceModel.Security.SymmetricSecurityProtocol.TryGetTokenSynchronouslyForOutgoingSecurity(Message message, SecurityProtocolCorrelationState correlationState, Boolean isBlockingCall, TimeSpan timeout, SecurityToken& token, SecurityTokenParameters& tokenParameters, SecurityToken& prerequisiteWrappingToken, IList`1& supportingTokens, SecurityProtocolCorrelationState& newCorrelationState)
at System.ServiceModel.Security.SymmetricSecurityProtocol.SecureOutgoingMessageCore(Message& message, TimeSpan timeout, SecurityProtocolCorrelationState correlationState)
at System.ServiceModel.Security.MessageSecurityProtocol.SecureOutgoingMessage(Message& message, TimeSpan timeout, SecurityProtocolCorrelationState correlationState)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.DoOperation(SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.GetTokenCore(TimeSpan timeout)
at System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionClientSettings`1.ClientSecuritySessionChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at OMG.Admin.DemoApp.Business.QuoteService.IQuoteService.GetQuotes(User quoteUser)
at OMG.Admin.DemoApp.Business.QuoteServiceClient.GetQuotes(User quoteUser) in C:\OMG_TFS01\OMG.Admin\OMG.Admin.DemoApp\OMG.Admin.DemoApp.Business\QuoteServiceClient.cs:line 131
at OMG.Admin.DemoApp.Business.QuoteBO.GetQuoteList() in C:\OMG_TFS01\OMG.Admin\OMG.Admin.DemoApp\OMG.Admin.DemoApp.Business\QuoteBO.cs:line 26
at OMG.Admin.DemoApp.Web.Services.DemoAppService.GetQuotes() in C:\OMG_TFS01\OMG.Admin\OMG.Admin.DemoApp\OMG.Admin.DemoApp.Web\Services\DemoAppService.svc.cs:line 27
at SyncInvokeGetQuotes(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
InnerException: System.InvalidOperationException
Message=The address of the security token issuer is not specified. An explicit issuer address must be specified in the binding for target 'https://myADFSserver/adfs/services/trust/13/issuedtokenmixedsymmetricbasic256' or the local issuer address must be configured in the credentials.
Source=mscorlib
StackTrace:
Server stack trace:
at System.ServiceModel.ClientCredentialsSecurityTokenManager.CreateIssuedSecurityTokenProvider(InitiatorServiceModelSecurityTokenRequirement initiatorRequirement)
at System.ServiceModel.ClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement, Boolean disableInfoCard)
at Microsoft.IdentityModel.Protocols.WSTrust.FederatedClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
at System.ServiceModel.Security.SecurityProtocol.AddSupportingTokenProviders(SupportingTokenParameters supportingTokenParameters, Boolean isOptional, IList`1 providerSpecList)
at System.ServiceModel.Security.SecurityProtocol.OnOpen(TimeSpan timeout)
at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.ClientSecurityChannel`1.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at System.ServiceModel.ICommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout)
InnerException:
I'm sure I'm missing something in the configuration and/or code can someone help me out?
I got this scenario working, here’s the solution for anyone interested.
Followed Dominick Baier’s post for ideas / code: http://leastprivilege.com/2010/10/14/wif-adfs-2-and-wcfpart-5-service-client-more-flexibility-with-wstrustchannelfactory/
I changed the back-end WCF service config to this:
<microsoft.identityModel>
<service>
<audienceUris>
<add value="https://localhost/Service/QuoteService.svc" />
<add value="https://localhost/Service/" />
</audienceUris>
<serviceCertificate>
<certificateReference x509FindType="FindByThumbprint" findValue="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
</serviceCertificate>
<issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<trustedIssuers>
<add thumbprint="000000000000000000000000000000000000" name="http://myADFSserver/adfs/services/trust" />
</trustedIssuers>
</issuerNameRegistry>
<certificateValidation certificateValidationMode="None" />
</service>
</microsoft.identityModel>
<system.serviceModel>
<services>
<service name="Service.QuoteService">
<endpoint address=""
binding="ws2007FederationHttpBinding"
contract="Service.IQuoteService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<ws2007FederationHttpBinding>
<binding>
<security mode="TransportWithMessageCredential">
<message establishSecurityContext="false">
<issuerMetadata address="https://myADFSserver/adfs/services/trust/mex" />
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpsGetEnabled="true" />
<federatedServiceHostConfiguration />
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="federatedServiceHostConfiguration"
type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
I’m no longer using WCF config on the client, it’s all done in code.
Here’s the client code:
public QuoteServiceClient()
{
SecurityToken actAsToken = this.GetDelegatedTokenUsername();
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.EstablishSecurityContext = false;
ChannelFactory<IQuoteServiceChannel> factory =
new ChannelFactory<IQuoteServiceChannel>(binding, new EndpointAddress(svcEndpoint));
factory.ConfigureChannelFactory<IQuoteServiceChannel>();
factory.Credentials.SupportInteractive = false;
this.channel = factory.CreateChannelWithIssuedToken<IQuoteServiceChannel>(actAsToken);
}
private SecurityToken GetDelegatedTokenUsername()
{
var binding = new UserNameWSTrustBinding();
binding.SecurityMode = SecurityMode.TransportWithMessageCredential;
//UserNameMixed is this endpoint "/adfs/services/trust/13/usernamemixed"
WSTrustChannelFactory trustChannelFactory = new WSTrustChannelFactory(binding, new EndpointAddress(UserNameMixed));
trustChannelFactory.TrustVersion = System.ServiceModel.Security.TrustVersion.WSTrust13;
trustChannelFactory.Credentials.SupportInteractive = false;
//Some User Account
//It's used to access the ADFS Server
//Act as is the actual Identity that Will be used.
//If you use one of windows bindings (ex. windowstransport), you wont need this.
//The AppPool identity will be used then.
trustChannelFactory.Credentials.UserName.UserName = #"domain\username";
trustChannelFactory.Credentials.UserName.Password = "password";
try
{
RequestSecurityToken rst = new RequestSecurityToken();
rst.RequestType = WSTrust13Constants.RequestTypes.Issue;
rst.AppliesTo = new EndpointAddress(ServiceAppliesTo);
//This part will give you identity of logged in user
rst.ActAs = new SecurityTokenElement(this.GetBootStrapToken());
var channel = trustChannelFactory.CreateChannel();
RequestSecurityTokenResponse rstr = null;
SecurityToken delegatedToken = channel.Issue(rst, out rstr);
return delegatedToken;
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
finally
{
try
{
if (trustChannelFactory.State == CommunicationState.Faulted)
{
trustChannelFactory.Abort();
}
else
{
trustChannelFactory.Close();
}
}
catch (Exception)
{ }
}
}
private SecurityToken GetBootStrapToken()
{
ClaimsPrincipal myClaimsPrincipal = System.Web.HttpContext.Current.User as ClaimsPrincipal;
SecurityToken bootstrapToken = myClaimsPrincipal.Identities[0].BootstrapToken;
if (bootstrapToken == null)
{
throw new Exception("bootstrap tokein is null. Logout and try again.");
}
return bootstrapToken;
}
That is all good and dandy, except you will not have proper claims on the back-end WCF service. Using this great article I was able to sort out the claim stuff in ADFS: http://technet.microsoft.com/en-us/library/adfs2-identity-delegation-step-by-step-guide.aspx . Scroll down to Enabling Identity Delegation and Fixing Claims Issuance Rules at CONTOSODC. I also removed claim encryption from Passively Federated Website.
After doing this I have same claims in the app service and the back-end WCF service.
I hope this helps someone in the same boat as I was.