5

I have made a simple RESTful Web Service (GET-only, for now) using the Microsoft ASP.NET MVC 4 ApiController.

Now I'm looking for the right way of implementing an authorization system for the service. I know I don't want to use the built-in FormsAuthentication, since I don't want to have a unique login page for all the applications using my WS; moreover, that breaks the RESTful paradigm, forcing a redirection and not notifying the client with the proper 401 status code.

So I have disabled FormsAuthentication deleting the following lines from my web.config:

<authentication mode="Forms">
    <forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>

and adding the following:

<modules runAllManagedModulesForAllRequests="true">
    <remove name="FormsAuthentication" />
</modules>

I already have an ApiController for managing the User login, which basically checks the credentials against my database and returns the user or a 401 if the credentials are not valid.

I have read that I have to implement the Membership and Authorization API, but I found nothing that helps me doing from scratch. Do you have any ideas? Do I need to manage cookies and authcodes on the database or is there a similar class to FormsAuthentication that does it for me?

frapontillo
  • 10,499
  • 11
  • 43
  • 54

3 Answers3

3

You could write a custom message handler to handle authentication. Dominick Baier wrote en excellent series of blog posts which delves into the details.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
3

I found a solution, I just basically used the workaround shown in the example by Microsoft.

  1. Create a folder called App_Start.
  2. Put the two classes with the proper namespaces.
  3. FormsAuthentication and the added request/response handling system will do the rest.

Since I didn't like the "Content moved here" in my 401 response, I have edited the OnEndRequest method this way:

private void OnEndRequest(object source, EventArgs args)
    {
        var context = (HttpApplication)source;
        var response = context.Response;

        if (context.Context.Items.Contains("__WEBAPI:Authentication-Fixup"))
        {
            response.StatusCode = (int)context.Context.Items[FixupKey];
            response.RedirectLocation = null;
            // Clear the page content, since I don't want the "Content moved here." body
            response.ClearContent();
        }
    }

References:

frapontillo
  • 10,499
  • 11
  • 43
  • 54
2

Checkout this project on github. They have developed some classes, with examples, for adding security to the ASP.NET Web API. One of the security models supported is basic authentication, which seems to be what you are describing in your question.

Kevin Junghans
  • 17,475
  • 4
  • 45
  • 62
  • It looks like I need the first example, `BasicAuthentication`. But I haven't yet understood if there's a way to store the authcode (I won't send username and password to the client as authcode) in a database. – frapontillo Mar 28 '12 at 14:09
  • I am not sure I understand what you mean by "a way to store the authcode." What is your description of the authcode. With basic authentication you want to encode the username/password sent over and decode it on the other end. You also want to use HTTPS/SSL/TSL with basic authentication to encrypt the whole message on the wire. When storing passwords in a DB I always use one way encryption for the stored password. Then you use the same encryption on the user entered password before doing a comparison of what is in the DB. – Kevin Junghans Mar 28 '12 at 14:40
  • I'd like to create a temporary authcode for each login and store it in a database. Which I think is the same thing that FormsAuthentication does: it creates a session authorization code strictly linked to the logged user. – frapontillo Mar 28 '12 at 15:47
  • Let me explain better: if I download [this sample project](http://code.msdn.microsoft.com/ASPNET-Web-API-JavaScript-d0d64dd7) by Microsoft and I start the web application, on the first registration it automatically creates a default database with user data. Then, when I log in, the web app sets a cookie called .ASPXAUTH, which is different every time I log out. Which means the server does not check the cookie value against username and password, but against a stored value. I want to achieve the same thing using the User table I already have. – frapontillo Mar 28 '12 at 16:37
  • I believe you are describing token authentication, which is also supported in the library I previously mentioned. There is a good discussion in this post on considerations for using this approach [http://stackoverflow.com/questions/1432664/best-way-to-create-a-token-system-to-authenticate-web-service-calls]. Basically you need to create web service method for logon that returns a token (authcode) for the client to use for any further service calls. You do need to add time outs to the authcode when using this method. – Kevin Junghans Mar 28 '12 at 17:47