Reputation: 7818
Using Basic Authentication, and the asp.net Web-Api, where JSON Get/Post's to my API, I need to check that the username/password exists in the membership table. Which the code below does:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Security;
namespace MvcApplication4.Filter
{
public class BasicAuthenticationAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (actionContext.Request.Headers.Authorization == null)
{
actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
else
{
string authToken = actionContext.Request.Headers.Authorization.Parameter;
string decodedToken = Encoding.UTF8.GetString(Convert.FromBase64String(authToken));
string username = decodedToken.Substring(0, decodedToken.IndexOf(":"));
string password = decodedToken.Substring(decodedToken.IndexOf(":") + 1);
if (Membership.Provider.ValidateUser(username, password))
{
// User exists in the membership table
}
else
{
// User doesn't exist - so return Unathorized
actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
}
}
}
}
I need to make reference to the username in my other controllers, to make sure the username also exists in a lookup table, which says which cars the user is allowed to query. I have a table in my database, and an associated class:
public class ApiMembers
{
public int id { get; set; }
public string UserName { get; set; }
public int car_id { get; set; }
}
[BasicAuthentication]
public IEnumerable<Cars> GetCars(long id)
{
var auth = dba.ApiMembers.Select(a => a.car_id == id && a.UserName=***AuthorisedUserName***).FirstOrDefault();
if (auth == null || !auth.Any())
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.Unauthorized));
}
else
{
// User exists in table, so give them info on car
}
My question is, without having to read the HTTP headers again, how do I get the UserName into the AuthorisedUserName part? Is there a way of "logging in" the user in the BasicAuthentication filter, or can you use session variables, like in webforms? Or is there a better way of knowing who has been authenticated in other controllers?
Upvotes: 2
Views: 1155
Reputation: 1039398
You could set the current principal:
if (Membership.Provider.ValidateUser(username, password))
{
// User exists in the membership table
var identity = new GenericIdentity(username);
Thread.CurrentPrincipal = new GenericPrincipal(identity, null);
}
Now inside your ApiController you could use the User property to access the currently connected username (remark this property was added in ASP.NET MVC 4 RC - in previous versions you could use the Request.GetPrincipal
extension method).
[BasicAuthentication]
public HttpResponseMessage Get()
{
string username = User.Identity.Name;
...
}
Upvotes: 3