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 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
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.
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?
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;
Well this works fine for me when I use windows azure. I think I have a bone to pick with my webhost
Pingback: Extensions to the Web API/MVC + Forms/Basic Auth Sample: Claims Transformation and AJAX | www.leastprivilege.com
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…
It should also work in VS2010. If not you’d need to pull out the code and start with a fresh 2010 solution.
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 ?
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..
Benjamin,
Take a look at SessionTokens:
https://leastprivilege.com/2012/06/19/session-token-support-for-asp-net-web-api/
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.
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?
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.
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?
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?
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.
If the user is already logged in and has a cookie – this would work. But only same-domain.
Got it. Thanks.
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
IIS/ASP.NET does not really support multiple auth types on the same application.
You can keep forms auth and basic auth in a single app. For windows I would use a separate. App in IIS.
Thank you for that clarification.
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!