REST WCF and Basic Authentication
Creating a REST API using WCF is not that complicated and requires some basic knowledge of WCF and web.config. But figure out how the heck to configure your server/solution to accept basic authentication and check login and password against .Net Membership API is a pain in the ass. Fortunately, we've found an easy way out! Here's what you gotta do:
1. Download WCF REST Starter Kit
http://aspnet.codeplex.com/releases/view/24644
From this solution you simply need Microsoft.ServiceModel.Web.dll to be referenced in your project.
2. Create a class called BasicAuthenticationInterceptor.cs
and copy&paste the following code:
using System.Collections.Generic;
using Microsoft.ServiceModel.Web;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
using System.Web.Security;
using System.Security.Principal;
using System.IdentityModel.Policy;
using System.ServiceModel;
using System.ServiceModel.Security;
using System.IdentityModel.Claims;
using System.Security.Cryptography;
namespace [Your-namespace].RestService.BasicAuthen
public class BasicAuthenticationInterceptor : RequestInterceptor
MembershipProvider provider;
public BasicAuthenticationInterceptor(MembershipProvider provider, string realm)
this.provider = provider;
protected MembershipProvider Provider
public override void ProcessRequest(ref RequestContext requestContext)
string[] credentials = ExtractCredentials(requestContext.RequestMessage);
if (credentials.Length > 0 && AuthenticateUser(credentials[0], credentials[1]))
InitializeSecurityContext(requestContext.RequestMessage, credentials[0]);
Message reply = Message.CreateMessage(MessageVersion.None, null);
HttpResponseMessageProperty responseProperty = new HttpResponseMessageProperty() { StatusCode = HttpStatusCode.Unauthorized };
responseProperty.Headers.Add("WWW-Authenticate",
String.Format("Basic realm=\"{0}\"", Realm));
reply.Properties[HttpResponseMessageProperty.Name] = responseProperty;
requestContext.Reply(reply);
private bool AuthenticateUser(string username, string password)
if (Provider.ValidateUser(username, password))
private string[] ExtractCredentials(Message requestMessage)
HttpRequestMessageProperty request = (HttpRequestMessageProperty)requestMessage.Properties[HttpRequestMessageProperty.Name];
string authHeader = request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("Basic"))
string encodedUserPass = authHeader.Substring(6).Trim();
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
string userPass = encoding.GetString(Convert.FromBase64String(encodedUserPass));
int separator = userPass.IndexOf(':');
string[] credentials = new string[2];
credentials[0] = userPass.Substring(0, separator);
credentials[1] = userPass.Substring(separator + 1);
private void InitializeSecurityContext(Message request, string username)
GenericPrincipal principal = new GenericPrincipal(new GenericIdentity(username), new string[] { });
List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>();
policies.Add(new PrincipalAuthorizationPolicy(principal));
ServiceSecurityContext securityContext = new ServiceSecurityContext(policies.AsReadOnly());
if (request.Properties.Security != null)
request.Properties.Security.ServiceSecurityContext = securityContext;
request.Properties.Security = new SecurityMessageProperty() { ServiceSecurityContext = securityContext };
class PrincipalAuthorizationPolicy : IAuthorizationPolicy
string id = Guid.NewGuid().ToString();
public PrincipalAuthorizationPolicy(IPrincipal user)
get { return ClaimSet.System; }
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
evaluationContext.AddClaimSet(this, new DefaultClaimSet(Claim.CreateNameClaim(user.Identity.Name)));
evaluationContext.Properties["Identities"] = new List<IIdentity>(new IIdentity[] { user.Identity });
evaluationContext.Properties["Principal"] = user;
3. Change Service.svc to the following:
<%@ ServiceHost Language="C#" Debug="true" Service="Service" Factory="AppServiceHostFactory" %>
using System.ServiceModel;
using System.ServiceModel.Activation;
using Microsoft.ServiceModel.Web;
using [your-solution-name].RestService.BasicAuthen;
class AppServiceHostFactory : ServiceHostFactory
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
WebServiceHost2 result = new WebServiceHost2(serviceType, true, baseAddresses);
result.Interceptors.Add(new BasicAuthenticationInterceptor(
System.Web.Security.Membership.Provider, "[your-solution-name]"));
4. In your web.config file make sure to add standard sql membership provider reference as well as to have authentication mode- None
<authentication mode="None"/>
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="SkyferLive" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/"/>
And at the end of your web.config make sure to add the following lines:
<serviceHostingEnvironment>
<baseAddressPrefixFilters>
<add prefix="http://[your-pc-name]"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>