I'm looking to write a config file that allows for RESTful services in WCF, but I still want the ability to 'tap into' the membership provider for username/password authentication.
The below is part of my current config using basicHttp binding or wsHttp w/out WS Security, how will this change w/ REST based services?
<bindings>
<wsHttpBinding>
<binding name="wsHttp">
<security mode="TransportWithMessageCredential">
<transport/>
<message clientCredentialType="UserName" negotiateServiceCredential="false" establishSecurityContext="false"/>
</security>
</binding>
</wsHttpBinding>
<basicHttpBinding>
<binding name="basicHttp">
<security mode="TransportWithMessageCredential">
<transport/>
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="NorthwindBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceAuthorization principalPermissionMode="UseAspNetRoles"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
Here's a podcast on securing WCF REST services with the ASP.net membership provider:
http://channel9.msdn.com/posts/rojacobs/endpointtv-Securing-RESTful-services-with-ASPNET-Membership/
I agree with Darrel that complex REST scenarios over WCF are a bad idea. It just isn't pretty.
However, Dominick Baier has some good posts about this on his least privilege blog.
If you'd like to see WSSE authentication support with fallback to FormsAuthenticationTicket support on WCF, check out the source code of BlogService.
Before you continue down this path of fighting to implement REST over WCF, I suggest you read this post by Tim Ewald. I was especially impacted by the following statement:
I'm not sure I want to build on a
layer designed to factor HTTP in on
top of a layer that was designed to
factor it out.
I've spent the last 12 months developing REST based stuff with WCF and that statement has proven itself to be so true over and over again. IMHO what WCF brings to the table is outweighed by the complexity it introduces for doing REST work.
Regardless if the community has opinions against REST on WCF (I'm personally on the fence) Microsoft has taken a swipe at it, http://msdn.microsoft.com/en-us/netframework/cc950529.aspx
Yes agreed with Moto, a link off the WCF Starter Kit is the closest thing I saw to authentication of credentials using a custom HTTP header (http://msdn.microsoft.com/en-us/library/dd203052.aspx).
However I could not get the example going.
Try custombasicauth @ codeplex
UPDATE 01/23/2012
Since I wrote this question I've seen a much better approach to securing REST like web services in the wild. It sounded complex when I first heard about it but the idea is simple and all over the web for both web services and other secure communication.
It requires the use of public/private keys.
1.) each user (customer) of the endpoint will need to register with your REST web service
- a.) you give this user a private key that should not be shared with
anyone
- b.) you also generate a public key that can go over the wire
in plain text if need be (this will also be used to identify the client)
2.) each request from the user needs to generate a hash to sign the request
- a.) One example of this might look like: private key + a timestamp + encoded payload (if small enough like a simple user info to be updated for example)
- b.) you take these 3 (or whatever you decided on) and generate a 1 way hash (using hmac for example)
- c.) in the request being sent over the wire you include the public key (so the server side knows who is attempting to send this request), the hash that was generated w/ the private key, and the timestamp.
3.) the server endpoint (your REST method) will need to generate a hash using the same inputs used on the client. This step will prove that both client and server knew a private key that matched the public key passed along with the request. (this in turn means that the user sending the request is legit as no one else could know the private key)
a.) lookup the customers private key by the public key being passed along during the request
b.) take the other params (timestamp and the encoded payload) along with the private key you found in the previous step and use the same algorithm to generate a 1 way hash (again hmac is what I've seen used in the real world)
- c.) the resulting 1 way hash needs to match the hash sent over the wire, if not send back a 400 (or whatever http code you deem to be a "bad request")