title: User/Pass Authentication using RESTful WCF & Windows Forms
body: <p>What is the best approach to implementing authorisation/authentication for a Windows Forms app talking to an IIS-hosted RESTful WCF Service?</p>
  
  <p>The reason I ask is I am very confused, after sifting through different articles and posts expressing a different method and eventually hitting a ~650 page document on WCF Security Best Practices" (<a href="http://www.codeplex.com/WCFSecurityGuide" rel="nofollow noreferrer">http://www.codeplex.com/WCFSecurityGuide</a>) I am just uncertain which approach is the BEST to take and how to get started on implementation, given my scenario.</p>
  
  <p>I started with this article "A Guide to Designing and Building RESTful Web Services with WCF 3.5" (<a href="http://msdn.microsoft.com/en-us/library/dd203052.aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/library/dd203052.aspx</a>) and a PDC video on RESTful WCF services, which was great and helped me implement my first REST-friendly WCF service,</p>
  
  <p>After I had the service working, I returned to implement security, see. "Security Considerations" (quarter down the page) and attempted to implement a HTTP Authorization header as per the instructions, however I found the code to be incomplete (see how 'UserKeys' variable was never declared).  This is the point at which I tried to research more on how to do this (using a HMAC hash with the "Authorization" HTTP header, but could not find much on google?) it led me to other articles regarding message-level security, forms auth and custom validators and frankly I am not sure which is the best and most appropriate approach to take now.</p>
  
  <p>So with all that said (and thanks for listening up till now!), I guess my main questions are,<br /></p>
  
  <p><strong>- Which security implementation should I use?<br /><br />
    - Is there any way to avoid sending the username/password with every WCF call? I would prefer not to send these extra bytes if a connection has been established at the beginning, which it will be before subsequent calls are allowed to be made after login.<br /><br />
    - Should I even really be concerned about anything other than plain text if I am using SSL?</strong></p>
  
  <p>As said, .NET 3.5 win forms app, IIS-hosted WCF service, however what is important is I wish any and all WCF services to require this authorization procedure (however it should be, session, http header or otherwise) as I do not want anybody to be able to hit these services from the web.</p>
  
  <p>I know the above post is large but I had to express the route I have already been down and what I need to accomplish, any and all help is greatly appreciated.</p>
  
  <p>PS: I am also aware of this post <a href="https://stackoverflow.com/questions/141484/how-to-configure-secure-restful-services-with-wcf-using-usernamepassword-ssl">How to configure secure RESTful services with WCF using username/password + SSL</a> and if the community suggests I move away from REST for WCF services, I can do this, however I started with this to keep consistency for any public APIs to come.</p>
  
  <p>I think it's important I state how I am accessing my WCF Service (contacting the service is working, but what is the best way to validate credentials - and then return the Member object?):</p>
  
  <pre><code>WebChannelFactory&lt;IMemberService&gt; cf = new WebChannelFactory&lt;IMemberService&gt;(
                  new Uri(Properties.Settings.Default.MemberServiceEndpoint));
              IMemberService channel = cf.CreateChannel();
              Member m = channel.GetMember("user", "pass");
  </code></pre>
  
  <p>Code that was half implemented from MS article (and some of my own for testing):</p>
  
  <pre><code> public Member GetMember(string username, string password)
      {
          if (string.IsNullOrEmpty(username))
              throw new WebProtocolException(HttpStatusCode.BadRequest, "Username must be provided.", null);
          if (string.IsNullOrEmpty(password))
              throw new WebProtocolException(HttpStatusCode.BadRequest, "Password must be provided.", null);
  
          if (!AuthenticateMember(username))
          {
              WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.Unauthorized;
              return null;
          }
  
          return new Member() { Username = "goneale" };
      }
  </code></pre>