SSL implementation for WCF Rest Service - wcf

<system.serviceModel>
<!--WCF Service-->
<services>
<service name="Service.RestServices">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="Service.IRestServices"/>
<endpoint address="mex"
binding="mexHttpsBinding"
contract="Service.IRestServices" />
</service>
</services>
<!--WCF Binding-->
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<!--WCF Behaviors-->
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata 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"/>
</behavior>
</serviceBehaviors>
</behaviors>
Is there anything else I want to consider in my Web.config file? Below is my service interface.
Service Interface(IRestServices)
[OperationContract]
[WebInvoke(ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, Method = "POST", UriTemplate = "Login", BodyStyle = WebMessageBodyStyle.Wrapped)]
When I am try to call using HTTPS then response I get is 404(Not Found), while using HTTP, I am getting response data properly.
How can I call my rest api web service(WCF) using HTTPS ?

We have to define factory in our WebService.svc file to support Https in WCF rest service
<%# ServiceHost Language="C#" Debug="true" Service="XcellenceIt.Plugin.Misc.NopRestApi.Service.RestServices" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

Related

Invoking WCF service in browser similar to asmx

I have made a WCF service in NET 4.0 and it returns the XML, I have tested it using SoapUI and i can see the required response xml. But my WCF service would be called by 3rd party software and they want to use it through a URL like asmx. I have googled and found that i need to make using REST guidelines. However i have not found a proper link showing making web-service using REST and then accessing the method from the browwer similar to web services.
Below is the interface code which i have used to return the format in XML
public interface IService1
{
[WebGet(
UriTemplate = "/GetDocument/",
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Xml)]
[OperationContract, XmlSerializerFormat]
XmlElement GetDocument();
// TODO: Add your service operations here
}
Below is my config settings.
<system.serviceModel>
<services>
<service name="BritishLandXML.BritishLandXML1" behaviorConfiguration="metadataBehavior">
<endpoint address="" binding="basicHttpBinding" contract="BritishLandXML.IService1" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<webHttpBinding>
<binding>
<security mode="None"></security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="rest">
<webHttp helpEnabled="true" faultExceptionEnabled="true" automaticFormatSelectionEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="metadataBehavior">
<!-- 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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
Please let me know how can i achieve this and what exact settings will be required.

WCF Silverlight enabled service "Not Found" error

I'm struggling with the following scenario (here is the big picture):
I have a WCF Silverlight-enabled service (based on the DomainService class) into my Web project. The service is designed to be called by the Silverlight 5 clients and also by non-Silverlight consumers.
The service displays the WSDL info at the address
"http://localhost/mywebapproot/Services/MailService.svc" and therefore it can
be discovered and implemented by any client within the Web
project (which is fine).
Here are the symptoms:
The service can't be called by any
Silverlight client (here is the problem!) The error returned is "The remote server returned an exception: Not Found". If I change the name of the
service in Web.Config (let's say I change
MyCompany.Web.Services.MailService into MailService), the service can
now be called by any Silverlight client but at that time the service
is no longer discoverable.
I put includeExceptionDetailInFaults at True and tried to inspect the service with Fiddler/HTTPDebuggerPro but they didn't give me any detailed information about the exception. It looks to me that the Silverlight clients, in this configuration and for some reason, aren't able to create the .SVC file on the fly.
Here is the implementation:
MailService.svc implementation
<%# ServiceHost Language="C#" Debug="true" Service="MyCompany.Web.Services.MailService" CodeBehind="MailService.svc.cs" %>
MailService.svc.cs implementation
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public sealed partial class MailService : DomainService, IMailService
{
}
IMailService interface
[ServiceContract(ConfigurationName = "MyCompany.Web.Services.IMailService")]
public interface IMailService
{
//Some public methods flagged as [OperationContract] go here
}
Web.Config implementation
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Secure_Behavior_Configuration">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="Public_MailService_BasicHttpBinding" transferMode="Streamed"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647"
maxBufferPoolSize="2147483647">
<readerQuotas maxArrayLength="21400000" maxStringContentLength="21400000" maxBytesPerRead="21400000"/>
<security mode="None"/>
</binding>
</basicHttpBinding>
<services>
<service name="MyCompany.Web.Services.MailService" behaviorConfiguration="Secure_Behavior_Configuration">
<endpoint
address=""
binding="basicHttpBinding"
bindingConfiguration="Public_MailService_BasicHttpBinding"
contract="MyCompany.Web.Services.IMailService" />
<endpoint
address=""
binding="basicHttpBinding"
bindingConfiguration="Secure_MailService_BasicHttpBinding"
contract="MyCompany.Web.Services.IMailService" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Thanks a lot for any help!
Chris.

WCF Windows authentication issue with REST service

I'm having some difficulty setting up a WCF service to run under Windows authentication. The service is only consumed via jQuery using ajax.
IIS (version 6 on server 2003) is set to only allow Windows Authentication.
web.config has the <authentication mode="Windows" /> tag.
Here's the service section of the web.config:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="AspNetAjaxBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<services>
<service name="SearchService" behaviorConfiguration="ServiceBehavior">
<endpoint address="http://localhost:9534/SearchService.svc" behaviorConfiguration="AspNetAjaxBehavior"
binding="webHttpBinding" bindingConfiguration="webWinBinding"
name="searchServiceEndpoint" contract="MyApp.Services.ISearchService">
</endpoint>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webWinBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>
<readerQuotas maxArrayLength="100000" maxStringContentLength="2147483647" />
</binding>
</webHttpBinding>
</bindings>
The interface looks like this:
[ServiceContract(Namespace = "http://MyService.ServiceContracts/2012/02", Name = "SearchService")]
public interface ISearchService
{
[WebGet(ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "GetSomeData?filter={filter}")]
[OperationContractAttribute(Action = "GetSomeData")]
string GetSomeData(string filter);
}
And the implementation:
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class SearchService : ISearchService
{
public string GetSomeData(string filter)
{
// Call Database and get some results
// return the results
return "";
}
}
When I navigate to the service in Internet Explorer, it prompts me for my username and password, despite having Windows Authentication turned on.
As soon as I enable Anonymous Authentication, the service loads just fine and everything works. Problem is, I have other things going on in the web application that require anonymous to be turned off.
I've scoured the web and can't find anything on this problem.

Call HTTPS REST service from WCF

I need to call some REST services from a third parties server over HTTPS. My thinking was that I would create myself a nice little WCF library to handle these calls and deserialise the responses. I'm coming a tad unstuck though.
The services I am trying to call have a test service that simply responds OK.
I have created an OperationContract in my interface as shown below:
[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Xml,
UriTemplate = "test")]
string Test();
In my service code I have a public method below:
public string Test()
{
ChannelFactory<IService1> factory = new ChannelFactory<IService1>("UMS");
var proxy = factory.CreateChannel();
var response = proxy.Test();
((IDisposable)proxy).Dispose();
return (string)response;
}
My app.config looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<client>
<endpoint address="https://61.61.34.19/serv/ums/"
binding="webHttpBinding"
behaviorConfiguration="ums"
contract="WCFTest.IService1"
bindingConfiguration="webBinding"
name="UMS" />
</client>
<services>
<service name="WCFTest.Service1" behaviorConfiguration="WCFTest.Service1Behavior">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8731/Design_Time_Addresses/WCFTest/Service1/" />
</baseAddresses>
</host>
<endpoint address ="" binding="wsHttpBinding" contract="WCFTest.IService1">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="ums">
<clientCredentials>
<clientCertificate findValue="restapi.ext-ags.801"
storeLocation="CurrentUser"
x509FindType="FindBySubjectName"/>
</clientCredentials>
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="WCFTest.Service1Behavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="webBinding">
<security mode="Transport">
<transport clientCredentialType="Certificate" proxyCredentialType="None"/>
</security>
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
I try to invoke the test method but receive the error "Could not establish trust relationship for the SSL/TLS secure channel with authority '61.61.34.19'."
Can anyone see what I'm missing here?
Any help appreciated. Cheers.
Could not establish trust relationship for the SSL/TLS secure channel with authority '61.61.34.19'.
This typically means there's a problem with the server's SSL cert. Was it self-signed? If so, you have to establish trust for the cert, typically by trusting the issuing CA or installing the cert in the windows cert store.
Try changing the webHttpBinding security setting from "Transport" to "None".

Wcf Basic authentication

Having some trouble using basic authentication with a simple test Wcf service. I am getting an exception:
The requested service, 'http://qld-tgower/test/Service.svc' could not be activated. See the > server's diagnostic trace logs for more information.
And in the trace log it shows:
The authentication schemes configured on the host ('Basic') do not allow those configured on the binding 'BasicHttpBinding' ('Anonymous'). Please ensure that the SecurityMode is set to Transport or TransportCredentialOnly. Additionally, this may be resolved by changing the authentication schemes for this application through the IIS management tool, through the ServiceHost.Authentication.AuthenticationSchemes property, in the application configuration file at the <serviceAuthenticationManager> element, by updating the ClientCredentialType property on the binding, or by adjusting the AuthenticationScheme property on the HttpTransportBindingElement.
But what I don understand it when I us the incorrect username and password it says it IS using basic authentication?
The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was 'Basic realm="qld-tgower"'.
This is my web.config details
<system.serviceModel>
<services>
<service name="WcfService"
behaviorConfiguration="Behavior">
<endpoint address="http://QLD-TGOWER/test/Service.svc"
binding="basicHttpBinding"
bindingConfiguration="httpBinding"
contract="IService" />
</service>
</services>
<diagnostics>
<endToEndTracing activityTracing="false" messageFlowTracing="true" propagateActivity="true"></endToEndTracing>
</diagnostics>
<bindings>
<basicHttpBinding>
<binding name="httpBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" proxyCredentialType="Basic">
</transport>
</security>
</binding>
</basicHttpBinding>
</bindings>
<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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
and this is my App.config
<system.serviceModel>
<diagnostics>
<endToEndTracing activityTracing="true" />
<messageLogging logMessagesAtTransportLevel="true" />
</diagnostics>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" >
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" proxyCredentialType="Basic"></transport>
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://QLD-TGOWER/test/Service.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService" contract="ServiceReference1.IService"
name="BasicHttpBinding_IService" />
</client>
</system.serviceModel>
my test application
private static void Main(string[] args)
{
var proxy = new ServiceClient("BasicHttpBinding_IService");
var clientCredentials = proxy.ClientCredentials;
clientCredentials.UserName.UserName = "username";
clientCredentials.UserName.Password = "password";
var res = proxy.GetData(1);
Console.WriteLine(res);
Console.WriteLine("Done");
Console.ReadKey(true);
}
And my service
public class Service : IService
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
Is there something that I am missing here?
Change the name and contract of the service to include the namespace.
Also, remove the endpoint address (set it to "") and don't include proxyCredentialType in the transport tag.
End result of the web.config should look something like this
<system.serviceModel>
<services>
<service name="MyNameSpace.MyService" behaviorConfiguration="asdf">
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="httpBinding" contract="MyNameSpace.IMyService" />
</service>
</services>
<diagnostics>
<endToEndTracing activityTracing="true" messageFlowTracing="true"
propagateActivity="true">
</endToEndTracing>
</diagnostics>
<bindings>
<basicHttpBinding>
<binding name="httpBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="asdf">
<!-- 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="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false"/>
</system.serviceModel>
Try for both client and server configs
<basicHttpBinding>
<binding name="BasicHttpBinding_IService">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
Install/Enable basic authentication
You may also need to install and apply basic authentication in IIS.
Goto "Programs and Features" / "Turn windows features on/off ".
Enable "basic authentication" somewhere under IIS and security.
I closed and opened the IIS console and was able to enable it under authentication settings.
This of course if for a development testing and it warns you about not having an SSL certificate.
You're not allowed to use username authentication over an unsecured connection
You can secure the message by using a secure transport (e.g. SSL) or message encryption (using certificates)
I have used ClearUsernameBinding in the past to great success, but I don't recommend it in production. I used it so that I could keep all my authentication code the same without requiring SSL in dev/test environments, but having it work with SSL by changing the configuration only.
Note: that custom binding isn't perfect, and I had to change it a bit to enable certain configuration changes.
This is what solved the issue for me:
<bindings>
<basicHttpBinding>
<binding>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
For reference see:
https://msdn.microsoft.com/en-gb/library/ff648505.aspx