vendredi 30 janvier 2015

HttpModule Web Api

I'm trying to get an auth basic on my web api. I've written a simple HttpModule to check it



public class BasicAuth : IHttpModule
{
SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["Connection"].ConnectionString);
private const string Realm = "MyRealm";

public void Init(HttpApplication context)
{
// Register event handlers
context.AuthorizeRequest += new EventHandler(OnApplicationAuthenticateRequest);
context.EndRequest += new EventHandler(OnApplicationEndRequest);
}

private static void SetPrincipal(IPrincipal principal)
{
Thread.CurrentPrincipal = principal;
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
}

private bool CheckPassword(string username, string password)
{
var parameters = new DynamicParameters();
parameters.Add("@UserName", username);
parameters.Add("@Password", password);
con.Open();
try
{
var query = //query to db to check username and password
return query.Count() == 1 ? true : false;
}
catch
{
return false;
}
finally
{
con.Close();
}
}

private bool AuthenticateUser(string credentials)
{
try
{
var encoding = Encoding.GetEncoding("iso-8859-1");
credentials = encoding.GetString(Convert.FromBase64String(credentials));

int separator = credentials.IndexOf(':');
string name = credentials.Substring(0, separator);
string password = credentials.Substring(separator + 1);

if (CheckPassword(name, password))
{
var identity = new GenericIdentity(name);
SetPrincipal(new GenericPrincipal(identity, null));

return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}

private void OnApplicationAuthenticateRequest(object sender, EventArgs e)
{
var authHeader = request.Headers["Authorization"];
if (authHeader != null)
{
var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);

// RFC 2617 sec 1.2, "scheme" name is case-insensitive
if (authHeaderVal.Scheme.Equals("basic",
StringComparison.OrdinalIgnoreCase) &&
authHeaderVal.Parameter != null)
{
if (AuthenticateUser(authHeaderVal.Parameter))
{
//user is authenticated
}
else
{
HttpContext.Current.Response.StatusCode = 401;
}
}
else
{
HttpContext.Current.Response.StatusCode = 401;
}
}
catch
{
HttpContext.Current.Response.StatusCode = 401;
}
}

private static void OnApplicationEndRequest(object sender, EventArgs e)
{
var response = HttpContext.Current.Response;
if (response.StatusCode == 401)
{
response.Headers.Add("WWW-Authenticate",
string.Format("Basic realm=\"{0}\"", Realm));
}
}

public void Dispose()
{
}
}


well, this code works pretty well, except the fact it asks for basic auth even on controller I don't put the [Authorize] tag on. And when it occurs, it gives the right data back.


Let me explain:


My HistoryController has [Authorize] attribute, to make a POST request I have to send Header auth to get data, if I don't do it, I receive 401 status code and a custom error.


My HomeController doesn't have [Authorize] attribute, if i make a get request on my homepage, the browser popups the authentication request, but if I hit Cancel it shows my home page. (The page is sent back with 401 error, checked with fiddler).


Where am I doing wrong?





Aucun commentaire:

Enregistrer un commentaire