Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Side by side Basic and Forms Authentication with ASP.NET Web API

Disclaimer: let me start by saying that I am new to MVC4 + Web Api + Web Services in general + JQuery. I might be attacking this on the wrong angle.

I am trying to build a Web MVC App + Web API in C# for .NET 4 to deploy in Azure. The web api will be used by mobile clients (iOS, using RestKit).

The Web MVC App will be relatively simple. We would like to use Forms Authentication for it and SimpleMembership - which we achieved and works fine.

We'll use the Web API methods from JQuery (Knockout) scripts to fill pieces of the web pages. Therefore, we expect the JQuery to use the same identity authenticated by Forms Authentication.

However, the idea is that the Web Api can be called directly by mobile clients. No Forms Authentications for those.

We have been looking at the Thinktecture Identity Model (http://nuget.org/packages/Thinktecture.IdentityModel https://github.com/thinktecture/Thinktecture.IdentityModel.40). We added the BasicAuth and AcessKey handlers to the config and it works (see code below).

When you try to access the webapi without being authenticated the browser displays the basic authentication dialog and works as expected.

The "issue" is that when you ARE already logged in via Forms Authentication and try to call a Web Api method you still get the Basic Authentication dialog. In other words, Thinktecture IdentityModel seems to ignore the Forms Authentication altogether.

My questions are:

  1. Are my expectations correct? that once I have done the forms authentication I shouldn't do anything else to let the JQuery scripts, etc., access the Web API from the same browser user session.
  2. How do I fix it?
  3. If my expectations are not correct; how is this supposed to work? ie: how do I make the JQuery scripts authenticate?

I know there are tons of similar questions in Stackoverflow, I honestly looked a lot of up, saw videos, etc., but either I am missing something obvious or there is no clear documentation about this for somebody new in the technologies.

I appreciate the help. Thanks.

public static AuthenticationConfiguration CreateConfiguration()
{
var config = new AuthenticationConfiguration
        {
            DefaultAuthenticationScheme = "Basic",
            EnableSessionToken = true,
            SetNoRedirectMarker = true
        };            

config.AddBasicAuthentication((userName, password) => userName == password, retainPassword: false);
config.AddAccessKey(token =>
        {
            if (ObfuscatingComparer.IsEqual(token, "accesskey123"))
            {
                return Principal.Create("Custom",
                    new Claim("customerid", "123"),
                    new Claim("email", "[email protected]"));
            }

            return null;
        }, AuthenticationOptions.ForQueryString("key"));
like image 886
rufo Avatar asked Oct 22 '12 01:10

rufo


People also ask

What is basic authentication in ASP.NET Web API?

Basic authentication works as follows: If a request requires authentication, the server returns 401 (Unauthorized). The response includes a WWW-Authenticate header, indicating the server supports Basic authentication. The client sends another request, with the client credentials in the Authorization header.

Can we use Web API with ASP.NET web form?

Although ASP.NET Web API is packaged with ASP.NET MVC, it is easy to add Web API to a traditional ASP.NET Web Forms application. To use Web API in a Web Forms application, there are two main steps: Add a Web API controller that derives from the ApiController class. Add a route table to the Application_Start method.

How do I create authentication and authorization in Web API?

Web API assumes that authentication happens in the host. For web-hosting, the host is IIS, which uses HTTP modules for authentication. You can configure your project to use any of the authentication modules built in to IIS or ASP.NET, or write your own HTTP module to perform custom authentication.


1 Answers

Here is the solution for this problem which I have come up with earlier.

Note: This solution doesn't involve Thinktecture Identity Model.

I have an abstract BasicAuthenticationHandler class which is a delegating handler. You can get this handler by installing the latest stable WebAPIDoodle NuGet package.

You can give a hint to this base basic authentication handler to suppress the authentication process if the request has been already authentication (e.g: by forms auth). Your custom handler that you need to register would look like as below:

public class MyApplicationAuthHandler : BasicAuthenticationHandler {

    public MyApplicationAuthHandler() 
        : base(suppressIfAlreadyAuthenticated: true) { }

    protected override IPrincipal AuthenticateUser(
        HttpRequestMessage request, 
        string username, 
        string password, 
        CancellationToken cancellationToken) { 

        //this method will be called only if the request
        //is not authanticated.

        //If you are using forms auth, this won't be called
        //as you will be authed by the forms auth bofore you hit here
        //and Thread.CurrentPrincipal would be populated.

        //If you aren't authed:
        //Do you auth here and send back an IPrincipal 
        //instance as I do below.

        var membershipService = (IMembershipService)request
            .GetDependencyScope()
            .GetService(typeof(IMembershipService));

        var validUserCtx = membershipService
            .ValidateUser(username, password);

        return validUserCtx.Principal;
    }

    protected override void HandleUnauthenticatedRequest(UnauthenticatedRequestContext context) {

        // Do nothing here. The Autharization 
        // will be handled by the AuthorizeAttribute.
    }
}

As a final step, you will need to apply System.Web.Http.AuthorizeAttribute (not System.Web.Mvc.AuthorizeAttribute) to your controllers and action methods to give authorization for the specific roles and users.

I hope this helps to solve your problem.

like image 105
tugberk Avatar answered Sep 24 '22 17:09

tugberk