Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have a WebApi using Basic Auth nicely. And I have an MVC site using Forms Auth nicely. But here's the catch:

Client X has a dedicated database with any number of Contacts and Products. The MVC site is a dedicated site for them (via {clientId} routing), which allows their Contacts to log in (via Forms Auth) and place orders for their products. The Contact must be Form-ly logged in to place an order.

The product orders (need to) hit the WebApi to be recorded in the Client's database.

But since the WebApi uses Basic Auth to validate the Client, not the Contacts who placed the orders, every request comes back is 401 - Unauthorized.

I've checked out ThinkTecture as suggested by a number of posts here on SO, however it doesn't get me what I need because I'm not looking to allow Forms Auth in the WebApi. I don't want to authenticate the Contact from the Client's database in the WebApi, I want to authenticate the Client in the WebApi.

Has anyone come across a similar scenario and am I missing something glaringly obvious? Perhaps I need to implement both Forms and Basic on the site?

The very standard Api call I'm making from the site (where the UserName and Password are the Client's, not the Contact's):

var clientId = new Guid(RouteData.Values["clientId"].ToString());
var baseUrl = ConfigurationManager.AppSettings["ApiBaseAddress"];
var authHeader = Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", _shoppingCartSettings.UserName, _shoppingCartSettings.Password)));
var requestUrl = String.Format("api/{0}/inventory", clientId.ToString());

var httpWebRequest = WebRequest.Create(baseUrl + requestUrl);

httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, "Basic " + authHeader);
httpWebRequest.Method = "GET";
httpWebRequest.Accept = "application/json";
httpWebRequest.ContentType = "application/json";

try
{
    using (var httpWebResponse = httpWebRequest.GetResponse())
    {
        // we never get here because of a 401
    }
}
catch (WebException ex)
{
    using (var httpWebResponse = ex.Response)
    {
        // we always get here
    }
}

If I set up a separate test client and make the same call, it works great :/

share|improve this question
add comment

3 Answers 3

Is your Web API under the same virtual directory and configuration as the MVC site? It looks like the Forms Auth HTTP module kicks in for your API, which you don't want. As long as you don't plan to call the API directly from the browser, move it to a separate virtual directory that is set up exclusively for basic auth, no forms auth module in the web.config for the API.

share|improve this answer
    
Yep, they are definitely in separate virtual directories with their own configs. MVC site set to "Forms" and WebApi set to "None" in the web.configs. –  McCee May 16 at 16:46
    
Thanks for the push in the right direction. Got it figured out. –  McCee May 16 at 18:15
add comment

Why not have one login for your MVC site that has the ability to submit orders for every Client? It makes sense for your WebAPI to only allow Clients to submit orders for themselves. But I don't think it makes sense to have your MVC site authenticate as different Clients based on the Contact. Your MVC site would have to store the passwords for each Client.

Instead, create one login for the MVC site and give it the ability to submit an order for any Client.

share|improve this answer
add comment
up vote 0 down vote accepted

After much banging of head against the not-so-proverbial wall, and a much needed shove by @0leg, I've discovered the cause.

In the Properties of my WebApi project file under Web > Servers, the Visual Studio Development Server was being used with a Virtual Path of "/", whereas my MVC project file was set up to use the Local IIS Web Server. The MVC project also had the Apply server settings to all users (store in project file) option checked.

Setting both to use the local IIS server resolved it.

Upon further contemplation, this now seems logical since they were essentially running on different servers.

Posting this for posterity's sake.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.