WCF 4.0 REST username password authentication
Asked Answered
R

4

7

I have been struggling with username/password authentication/authorization in a WCF 4.0 RESTfull service using the ASP.Net membership/role providers.

Having spent two days trying to find something that most people agree on, I gave up. A lot of confusion seems to be because there is little information specifically for WCF 4.0.

Could someone be kind enough to

  1. Give an authoritative view on whether WCF 4.0 + REST is a good idea to begin with?
  2. Outline the generally accepted steps to do this (or links).
  3. Provide a reasonably complete sample of code needed to complete this.

Edit: Bounty for anyone who can provide a complete sample(or even just a link to a complete sample) with username/password Authentication and Authorization for a RESTfull WCF 4.0 service using the WCF service application template in VS 2010.

Richierichlad answered 18/9, 2011 at 23:15 Comment(6)
So IIS NT authentication is not a viable option?Careless
You can expose WCF contracts through an ASP.net Web Application project and possibly apply ASP.net authentication though that in your web.config.Careless
Would that not require using SOAP headers? Using the Membership and Roleproviders is not really the problem. Its wiring everything together that is.Richierichlad
Kick up an empty ASP.net Web Application, add a svc and change your web.config to suite. You may be pleasantly surprised. Ie #4950292Careless
Sorry I don't understand. How exactly will it be authenticated in the first place? Will that be Restfull?Richierichlad
What is the purpose of your service and what kind of applications are going to consume it?Scourings
S
10

I think that the answer to your question depends on the purpose of your service and the type of applications that are going to consume it.

If you have an existing ASP .Net application and you want to expose part of its functionality as a RESTfull service which you would be able to consume client side using AJAX, then WCF might not be the best option. In this particular case you already have an authentication user inside the web application and you want that authentication to get propagated during the AJAX calls. Implementing this is actually quite simple.

ASP .Net Forms authentication is based on authentication cookies which are generated and passed to the browser after a successful login. Each call made from the browser to any URL on the same domain as your application will also contain the authentication cookie. In ASP .Net MVC you can simply implement your service methods as Controller actions which require authorization and everything will happen for you behind the scenes.

In classic ASP .Net you can use PageMethods to implement your service methods and again the cookie will be sent and validated behind scenes for you (examples of PageMethods here and here).

On the other hand, if your service is going to be consumed outside the browser (for example from desktop or mobile applications), then WCF might indeed be the right tool for implementing the service. However, ASP .Net forms authentication is not the best choice for implementing security. The main purpose of REST services is simplicity so that clients can easily be implemented on every platform and the cookie based mechanism of ASP .Net forms authentication is not the most straight forward.

One protocol, specifically build for user authentication in the context of web services, is OAuth. It's second version is still in draft (find the specs here), but most probably this is the version you will want to use, since it is much simpler than OAuth 1.0. Facebook has already implemented its API Authentication over OAuth 2.0 (details here) and you might want to check their implementation for inspiration.

Besides user authentication, OAuth also ensures consuming application (service client) authentication and also makes sure that the user will never enter its credentials directly inside the client application. If that is a bit too much that what you actually need, you might create a custom implementation inspired from OAuth 2.0.

First of all you will need to expose your service over HTTPS so that all the communication between the service and client is encrypted. Second you will need to create a login method in the service like the following:

string Login(string user, string password);

On a successful login, the above method will return an authentication token. The authentication token will then be used and validated on all the other methods. For example:

Employee[] GetAllEmployees(string authToken)
{
  // verify token here

  // return data if user authenticated by token
}

In the above architecture, the authToken has the same role as the authentication cookie in ASP .Net forms authentication, but it is passed as a simple parameter. You will be responsible to implement the algorithm of generating the tokens (they must be long enough and unique, with an algorithm like here) and also storing and validating them.

Scourings answered 4/10, 2011 at 22:41 Comment(5)
how token will be accessed in GetAllEmployees as it doesn't maintains states..... authToken passed to GetAllEmployees will be checked with what?Osiris
@Anil, authTokens can be kept in different persistent data stores, like databases.Scourings
why not to use Headers instead of using databases to store and managing states at service layer....moreover it makes us to put extra overhead of destroying it periodically....client can add the headers, which we can verify the headers in application_AuthenticateRequest event...headers can contain anything like encrypted username and password or tokenOsiris
@Anil, headers are a way to pass data between clients and servers, not a way to store it. You can pass tokens using headers, but then you still need to validate them server side, which means that while they are alive, they need to be persisted in a data store. Databases are just an option for that, you can choose whatever is better suited for you. Passing encrypted user + password is a bad option because: a) it would be equivalent to an infinite login session (no way to control expiry, unless changing password), b) you should not store passwordsScourings
in that case, we need to pass username/password in the login method mentioned by you at service layer....which is again a security threat....(even though it is encrypted) .... as you mentioned first call the login method of service which will then issue token and then call rest methods using token passed to it....the method I stated doesn't need to be stored in a persisted data store ..... at server end you can keep that in the config keys (again encrypted) and compare it from config settings ... moroever I said you can pass either username / password or encrypted tokenOsiris
B
2

WCF Web Api makes writing WCF Rest service very easy however it comes with limitations. For authentication you will need to use WCF Rest Contrib

If you want maximum control over your service design then you should resort back to ASP.NET MVC and write controller methods for each service method.

Bibbie answered 19/9, 2011 at 6:9 Comment(0)
S
1

One approach is to use secure key. and token

  1. Every client has secure key which he sends on first request , probably in header.
  2. You can generate key like key = MD5Hash(username+password);
  3. In response he gets token the , the token is then sent in each request. Token can be Guid. Every token expired after x mins.
  4. On server side you can maintain a singleton dictionary like Dictionay , to check token expiration when current time > expiration time remove it from dictionary.
  5. To renew sessions put renew session method in your code.

For extream security

Have private/public key pair, client will encrypt entire post data using public key and you will decrypt using private key.

Sceptic answered 2/2, 2013 at 6:43 Comment(0)
S
-1

Here is an example done with asp.net mvc

When i call http://localhost:57322/Test/SecureMethod/ i get an error. However if i call http://localhost:57322/Test/Login?username=test&password=abc first then the original URL returns a valid result.

namespace MvcApplication1.Controllers
{
    public class TestController : Controller
    {
        public ActionResult Login(string username, string password)
        {
            if (username=="test" && password == "abc")
            {
                FormsAuthentication.SetAuthCookie(username, true);
                return Json(true, JsonRequestBehavior.AllowGet);
            }
            return Json(false, JsonRequestBehavior.AllowGet);
        }

        [Authorize]
        public ActionResult SecureMethod()
        {
            return Json("Hello world",JsonRequestBehavior.AllowGet);
        }

    }
}

If you already have .svc written and they are not done via MVC you can put them in any folder secured via web.config and then just use the Login method above to login before making any secure calls.

Swaggering answered 1/10, 2011 at 0:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.