I've built two projects, one ASP.NET Web API and one ASP.NET MVC. The MVC project gets the data from the API project. This is all well and good and I've tested the API project by using the HttpClient class and everything works correctly; however, now it's
time to secure the project.
I can easily secure the MVC project by using plain jane ASP.NET Membership Provider (which is the business case). I've added the AuthorizeAttribute (The HTTP one, not the MVC one) to the Web API controllers. Now, how would I secure the Web API project with
the same ASP.NET Membership Provider? I've tried using the HttpClient-HttpClientHandler tandem to pass credentials, however it's not working (it doesn't get pass the AuthorizeAttribute of the controllers). Here's my attempt at that:
HttpClientHandler handler = new HttpClientHandler();
handler.Credentials = new NetworkCredential("theUser", "thePassword");
HttpClient client = new HttpClient(handler);
HttpResponseMessage clientResult = client.GetAsync(
string.Format(@"{0}{1}",
ConfigurationManager.AppSettings["WebApiBaseUri"].ToString(),
@"Controller/Resource")
).Result;
var something = clientResult.Content.ReadAsAsync<JsonArray>().Result;
Ok, I think I am starting to get the point; just need your guidance here:
So, something like this code goes inside the client, right?
HttpClient client = new HttpClient() {BaseAddress = new Uri(@"http://localhost:14768/api")};
client.DefaultRequestHeaders.Authorization =
new BasicAuthenticationHeaderValue("userName", "@passw0rd");
//var authN = new HttpAuthentication(config);
////ClaimsPrincipal principal = authN.Authenticate
//config.AddBasicAuthentication((username, password) => Membership.ValidateUser(username, password));
var results = client.GetAsync("http://localhost:14768/api/Cars").Result;
Console.WriteLine();
and this code goes inside the Web API, right?
public ActionResult Get(int id)
{
private CarparkContext context = null;
// GET api/values
public List<Car> Get()
{
var config = new AuthenticationConfiguration
{
DefaultAuthenticationScheme = "Basic",
EnableSessionToken = true
};
var authN = new HttpAuthentication(config);
// TODO: WHERE DOES HttpResponseMessage COME FROM???
ClaimsPrincipal principal = authN.Authenticate(...);
config.AddBasicAuthentication((username, password) => Membership.ValidateUser(username, password));
return context.Cars.ToList();
}
}
quick question: Where will the HttpResponseMessage come from if, let's say, I just have a signature in my Get method of int id?
The client side is ok. For the service side, most of the code goes into global.asax. In the github repository there is a sample folder, inside that there is a full web API sample. Have a look at global.asax which calls out to a class called SecurityConfig.
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Resources.Configuration;
namespace WebApiSecurity
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
AuthenticationConfig.ConfigureGlobal(GlobalConfiguration.Configuration);
DependencyConfig.Configure(GlobalConfiguration.Configuration);
CorsConfig.RegisterGlobal(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
I'm still confused on a lot of levels about how I am supposed to use IdentityModel with ASP.NET Membership Provider; don't get me wrong, the examples help, but not that much. I am going to pass on securing my Web APIs using Claims until I can find a step-by-step
guide on how to do this starting from scratch (from launching Visual Studio 2012) all the way until deployment to IIS.
melech
Member
15 Points
7 Posts
Securing the API using ASP.NET Membership Provider
Jul 17, 2012 03:33 AM|LINK
Hi,
I've built two projects, one ASP.NET Web API and one ASP.NET MVC. The MVC project gets the data from the API project. This is all well and good and I've tested the API project by using the HttpClient class and everything works correctly; however, now it's time to secure the project.
I can easily secure the MVC project by using plain jane ASP.NET Membership Provider (which is the business case). I've added the AuthorizeAttribute (The HTTP one, not the MVC one) to the Web API controllers. Now, how would I secure the Web API project with the same ASP.NET Membership Provider? I've tried using the HttpClient-HttpClientHandler tandem to pass credentials, however it's not working (it doesn't get pass the AuthorizeAttribute of the controllers). Here's my attempt at that:
HttpClientHandler handler = new HttpClientHandler(); handler.Credentials = new NetworkCredential("theUser", "thePassword"); HttpClient client = new HttpClient(handler); HttpResponseMessage clientResult = client.GetAsync( string.Format(@"{0}{1}", ConfigurationManager.AppSettings["WebApiBaseUri"].ToString(), @"Controller/Resource") ).Result; var something = clientResult.Content.ReadAsAsync<JsonArray>().Result;Thanks
Mudasir.Khan
All-Star
15346 Points
3142 Posts
Re: Securing the API using ASP.NET Membership Provider
Jul 17, 2012 12:17 PM|LINK
use Session and have a Flag if project are deployed in same folders then they can share the session
dbaier
Member
264 Points
66 Posts
MVP
Re: Securing the API using ASP.NET Membership Provider
Jul 17, 2012 12:19 PM|LINK
Have a look here:
https://github.com/thinktecture/Thinktecture.IdentityModel.40
and
http://leastprivilege.com/2012/05/26/thinktecture-identitymodel-and-asp-net-web-api/
dominick
_____________________________
Dominick Baier - http://www.leastprivilege.com
melech
Member
15 Points
7 Posts
Re: Securing the API using ASP.NET Membership Provider
Jul 17, 2012 02:34 PM|LINK
Mudasir,
No good to use Sessions because they aren't sharing any folder. Thanks for trying though. :-)
Dominick,
Let me get back to you on this one; that's a lot of code to understand to perform authentication in ASP.NET Web API. :-)
melech
Member
15 Points
7 Posts
Re: Securing the API using ASP.NET Membership Provider
Jul 17, 2012 05:17 PM|LINK
Dominick,
Ok, I think I am starting to get the point; just need your guidance here:
So, something like this code goes inside the client, right?
HttpClient client = new HttpClient() {BaseAddress = new Uri(@"http://localhost:14768/api")}; client.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue("userName", "@passw0rd"); //var authN = new HttpAuthentication(config); ////ClaimsPrincipal principal = authN.Authenticate //config.AddBasicAuthentication((username, password) => Membership.ValidateUser(username, password)); var results = client.GetAsync("http://localhost:14768/api/Cars").Result; Console.WriteLine();and this code goes inside the Web API, right?
{private CarparkContext context = null; // GET api/values public List<Car> Get() { var config = new AuthenticationConfiguration { DefaultAuthenticationScheme = "Basic", EnableSessionToken = true }; var authN = new HttpAuthentication(config); // TODO: WHERE DOES HttpResponseMessage COME FROM??? ClaimsPrincipal principal = authN.Authenticate(...); config.AddBasicAuthentication((username, password) => Membership.ValidateUser(username, password)); return context.Cars.ToList(); }quick question: Where will the HttpResponseMessage come from if, let's say, I just have a signature in my Get method of int id?
Many thanks
dbaier
Member
264 Points
66 Posts
MVP
Re: Securing the API using ASP.NET Membership Provider
Jul 17, 2012 07:09 PM|LINK
dominick
_____________________________
Dominick Baier - http://www.leastprivilege.com
melech
Member
15 Points
7 Posts
Re: Securing the API using ASP.NET Membership Provider
Jul 18, 2012 04:19 PM|LINK
Hi Dominick,
I've checked that project and its Global.asax. There isn't any code that makes a call to a SecurityConfig class;
https://github.com/thinktecture/Thinktecture.IdentityModel.40/blob/master/Samples/Web%20API/WebHost/Global.asax.cs
I also double-checked the .NET 4.5 version:
https://github.com/thinktecture/Thinktecture.IdentityModel.45/blob/master/Samples/Web%20API/WebHost/Global.asax.cs
here are the contents of the Global.asax:
using System.Web.Http; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; using Resources.Configuration; namespace WebApiSecurity { public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); AuthenticationConfig.ConfigureGlobal(GlobalConfiguration.Configuration); DependencyConfig.Configure(GlobalConfiguration.Configuration); CorsConfig.RegisterGlobal(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); } } }dbaier
Member
264 Points
66 Posts
MVP
Re: Securing the API using ASP.NET Membership Provider
Jul 18, 2012 04:23 PM|LINK
Yeah - then try
AuthenticationConfig.ConfigureGlobal(GlobalConfiguration.Configuration);
;)
dominick
_____________________________
Dominick Baier - http://www.leastprivilege.com
melech
Member
15 Points
7 Posts
Re: Securing the API using ASP.NET Membership Provider
Jul 18, 2012 05:17 PM|LINK
I'm still confused on a lot of levels about how I am supposed to use IdentityModel with ASP.NET Membership Provider; don't get me wrong, the examples help, but not that much. I am going to pass on securing my Web APIs using Claims until I can find a step-by-step guide on how to do this starting from scratch (from launching Visual Studio 2012) all the way until deployment to IIS.
Nevertheless, marking as answer.