First of all, I am new to WCF. I created a REST webservice using WCF. It only has one operation that retrieves the list of products (in json format). This is invoked from web using jquery. It works perfectly.
Now, what I need is to add a custom authentication to the webservice. Is it possible to add it to webHttpBinding? I added the validation:
public class ServiceAuthenticator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (null == userName || null == password)
{
throw new ArgumentNullException();
}
if (userName != "testuser")
{
throw new SecurityTokenException("Unknown Username or Password");
}
}
}
And I tried to change web.config to make it work, but I can't.
This is my web.config working without custom authentication:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding crossDomainScriptAccessEnabled="true">
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="WCFEndPointBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyRestService.ServiceAuthenticator, MyRestService" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="MyRestService.ProductRESTService" behaviorConfiguration="ServiceBehavior">
<endpoint address=""
behaviorConfiguration="WCFEndPointBehavior"
binding="webHttpBinding"
contract="MyRestService.IProductRESTService">
<identity>
<dns
value="localhost"/>
</identity>
</endpoint>
</service>
</services>
Here is the jquery invoking the ws:
$("#myButton").click(function () {
var artistURL = "http://localhost:56866/ProductRESTService.svc/GetProductList/";
var returnData = "";
$.ajax({
cache: false,
type: "GET",
async: false,
processData: true,
data: "",
url: artistURL,
contentType: "application/json; charset=utf-8",
dataType: "jsonp",
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Basic " + btoa("testuser:123456789"));
},
error: function (request, status, error) { alert("Error"); },
success: function (data, status, jqXHR) {
$("div#myOutput").html(" ");
returnData = "<table style='font-size:12pt;font-family:sans-serif'><tr><th>Product</th><th></th></tr>";
for (prop in data) {
if (!data.hasOwnProperty(prop)) { continue; }
if (data[prop] != null) {
for (var i = 0; i < data[prop].length; i++) {
returnData += "<tr><td>" + data[prop][i]["ProductId"]
+ " " + data[prop][i]["Name"] + "</td><td align='right'>"
+ data[prop][i]["CategoryName"] + "</td></tr>";
}
}
}
returnData = returnData + "</table>";
$("div#myOutput").html(returnData);
}
});
return (false);
});
When i execute this, it works ok, but the custom validator is never reached. Is anything missing in my web.config? How can I apply custom authentication to this kind of webservices?
I am using: .NET Framework 4.5 IIS Express with VS2012
Thanks in advance!
EDIT!!!!!!!!!!!!!!!!!!
Authentication is performed by IIS, that is why the custom validation wasn't triggered. There are some workarounds:
- Self-hosted service,
- ISS-Hosted performing custom authentication with ServiceAuthorizationManager (it should be used for authorization, no authentication, but this is the only way I've found). Here you have more info: Basic Authentication with IIS hosted REST services using the webHttpBinding
If anyone has another workaround...you are free to comment! I hope this helps.