Mixing MVC + Forms Authentication and Web API + Basic Authentication

Got several emails recently with questions on how to enable the following scenario: ASP.NET application (e.g. MVC) using Forms Authentication and Web APIs using Basic Authentication to authenticate against a unified user store.

This is actually quite simple to achieve using Thinktecture.IdentityModel. I started with a standard MVC forms authentication template and used Membership to authenticate the user on the login page:

// authenticate user

var success = Membership.ValidateUser(model.UserName, model.Password);

 

if (success)

{

    // set authentication cookie

    FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);

 

    return RedirectToLocal(returnUrl);

}

 

Then I added the following lines of code to WebApiConfig.cs:

var authConfig = new AuthenticationConfiguration();

 

// setup authentication against membership

authConfig.AddBasicAuthentication((userName, password) => 
  Membership
.ValidateUser(userName, password));

           

config.MessageHandlers.Add(new AuthenticationHandler(authConfig));

 

Job done. Web app users use Forms Authentication with Membership to authenticate, Web API users use Basic Authentication with Membership to authenticate.

The full sample is here.

HTH

This entry was posted in ASP.NET, IdentityModel, WebAPI. Bookmark the permalink.

27 Responses to Mixing MVC + Forms Authentication and Web API + Basic Authentication

  1. Matthew Belk says:

    This is a surprisingly simple solution, Dominick. How does this work when our MVC views use knockout or other databinding JS that gets data from the WebAPI? Would the auth cookie that was established in the forms auth still apply here? How would we go about doing claims transformations in the solution that you present here?

    Thanks,
    Matthew

  2. JS would use the forms auth cookie. You would need to do claims transformation for MVC and Web API independently – but can use the same ClaimsAuthenticationManager of course. For Web API you just need to set the auth mgr on the AuthenticationConfiguration.

  3. Josh Barrett says:

    Dominick, I used this sample to add Basic auth using membership to my web api project. It works fine locally ( gives a 401 if info in head is missing or invalid, if I navigate in browser it prompts ) but when I put it up to my asp.net web host it never authenticates. (if I use a browser it chains the prompt)
    the only thing I have added to my project was the following in the webapiConfig
    using System.Web.Security;
    using Thinktecture.IdentityModel.Tokens.Http;
    var authConfig = new AuthenticationConfiguration();
    // setup authentication against membership
    authConfig.AddBasicAuthentication((userName, password) => Membership.ValidateUser(userName, password));
    config.MessageHandlers.Add(new AuthenticationHandler(authConfig));

    Am I missing something? If so, why does it work locally you think?

  4. Josh Barrett says:

    Sorry should have added that I tried to add basic auth using Piotr Walat DelegatingHandler from
    http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-message-handlers/

    and ended up with the exact same situation
    I thought it was the issue with HttpContext.Current.User that I have seen but even when I added the following lines
    Thread.CurrentPrincipal = principal;
    HttpContext.Current.User = principal;

  5. Pingback: Extensions to the Web API/MVC + Forms/Basic Auth Sample: Claims Transformation and AJAX | www.leastprivilege.com

  6. Terry Blankers says:

    This looks like just what I need. I’ve installed .NET 4.5 and MVC4. I wasn’t able to load the solution in VS2010. Do I need VS2012 or can I modify your project to get it to run in VS2010?

    Thanks…

  7. Benjamin N says:

    Exactly what I needed, many thanks.
    In my case, I consume my API controller directly in my MVC application so I’ve implemented the following:
    – When a user authenticates to the website, I store credentials in the form authentication ticket user data
    – Before any ajax call to web api, I do an ajax call to an mvc action in order to retrieve credentials and I use the “beforeSend” ajax callback in order to popuplate the authorisation header.
    This way, my authenticated user has access to all API methods.

    It’s a little bit complicated and I’m wondering if there is not any simple solution to do that.

    Any similar experience on your side ?

  8. rajesh says:

    Mixing MVC + Forms Authentication + Windows Authentication (I am using thinktecture STS)
    presently I am using forms authentication , but I got the requirement like mixing of Forms (internet claims based forms authentication)and Windows Authentication (intranet uses AD account authentication)
    can any one please help..

  9. Matt says:

    Benjamin,

    Take a look at SessionTokens:

    Session Token Support for ASP.NET Web API

  10. Ronald says:

    Dominick,
    I tried the latest FormAndBasicAuthentication under VS 2012, the client application never get back from web api call. I only get “Hello” at the prompt.
    Did I miss anything? Thanks in advance

    • Not sure – you have to debug/troubleshoot that i guess.

      • omair says:

        static Uri _address = new Uri(“https://localhost:34980/api/greeting”);

        static void Main(string[] args)
        {
        var client = new HttpClient { BaseAddress = _address };
        client.DefaultRequestHeaders.Authorization =
        new BasicAuthenticationHeaderValue(“alice”, “alice”);

        var response = client.GetAsync(“”).Result;

        Console.WriteLine(“Hello {0}”, response.Content.ReadAsStringAsync().Result);
        Console.ReadLine();
        }

        //Response shows that HTTPS is required so I add https://localhost:34980/api/greeting

        But I face the same problem .Only Hello is show on console window.

        Please guid us.

      • Have you debugged it?

    • Ronald says:

      I keeps myselef away from anything that its simplest example could even not work.

      • I am very sorry to hear that it does not work for you. It works for many other people.

        It’s just hard to tell what could be wrong, without you helping troubleshoot it.

  11. Wes says:

    So I’m trying to do this same thing but in a .NET 2.0 application (web site project) with calls to .NET 4.0 Web API. Anything you can say to point me in the right direction?

    • Well – this is not the same thing, right? Web app and api are in different applications in your case. Or am I wrong?

      • Wes Fincher says:

        Correct, I misspoke…Seems to be a lot of noise out there around this so I’m a bit confused. Do I need to pass an Authentication header or cookie? Both? Or something else?

  12. José Araujo says:

    This works… however, I was expecting/hoping that if a given user was already logged in with WebForms, the basic authentication would be bypassed, like in this question: http://stackoverflow.com/questions/13004091/side-by-side-basic-and-forms-authentication-with-asp-net-web-api.

    Is there a simple way to accomplish it?

    Regards. Thanks.

  13. Jürgen Bäurle says:

    This is a fantastic blog, Domminick!

    I need your advice on how to enable the following scenario: ASP.NET MVC 4 application using Forms Authentication for the web front end to authenticate against a database user store and Web APIs using Basic Authentication for mobile clients and WIA for .NET clients (with DefaultNetworkCredentials) to authenticate against the Active Directory.

    How can is setup this configuration?

    Thanks in advance.

    Jürgen

  14. akrogers says:

    I have an MVC 5 site that I have added Web API to and want to secure my api controller. This solution works through a web browser for securing the api, however when I try to send the Authorization through the header from my mobile app, I get an “object reference not set to an instance of an object error” with code following suggesting it is trying to load the theme which makes me think it’s trying to direct to a login page. How can I get it to authorize without going to the login by passing the authentication in the header? Thank you for any help you can offer!

Leave a comment