Skip to content

Instantly share code, notes, and snippets.

@donnfelker
Created April 1, 2011 16:39
Show Gist options
  • Save donnfelker/898455 to your computer and use it in GitHub Desktop.
Save donnfelker/898455 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Text;
namespace Example.Core.Security
{
public class ApiPrincipal : GenericPrincipal
{
public ApiPrincipal(IIdentity identity, string[] roles) : base(identity, roles)
{
}
}
public class ApiIdentity : GenericIdentity
{
public ApiIdentity(string name) : base(name)
{
}
public ApiIdentity(string name, string type) : base(name, type)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Example.Web.Api.Services.ActionFilters;
namespace Example.Web.Api.Controllers
{
/// <summary>
/// Handles Examples
/// </summary>
public class ExampleController : Controller
{
[RequiresAuth]
public ActionResult Index()
{
return Json(new {authorized = true, user = User.Identity.Name}, JsonRequestBehavior.AllowGet);
}
}
}
using System;
using System.Text;
using System.Web;
using System.Web.Mvc;
using Example.Core.Security;
namespace Example.Web.Api.Services.ActionFilters
{
/// <summary>
/// Authenticates users with Basic WWW authorization or through username/password header auth.
/// http://stackoverflow.com/questions/1407153/rest-ful-basic-authentication-with-asp-net-mvc
/// </summary>
public class RequiresAuth : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
// This method supports both http authorization through the authorization header,
// or manual authorization by passing the username or password through the headers.
// Preferred method is www realm auth (Basic) over username/password header auth
// for security.
string auth = filterContext.HttpContext.Request.Headers["authorization"];
string username = filterContext.HttpContext.Request.Headers["username"];
string password = filterContext.HttpContext.Request.Headers["password"];
if (!String.IsNullOrEmpty(auth))
{
// user is using Basic auth realm authorization.
byte[] encodedDataAsBytes = Convert.FromBase64String(auth);
string val = Encoding.ASCII.GetString(encodedDataAsBytes);
string userpass = val.Replace("Basic ", "");
string user = userpass.Substring(0, userpass.IndexOf(':'));
string pass = userpass.Substring(userpass.IndexOf(':') + 1);
AuthorizeUser(filterContext, user, pass);
}
else if(String.IsNullOrEmpty(username) == false && String.IsNullOrEmpty(password) == false)
{
// User is using header auth w/ username and password headers.
AuthorizeUser(filterContext, username, password);
}
else
{
if (AuthorizeCore(filterContext.HttpContext))
{
HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
cachePolicy.SetProxyMaxAge(new TimeSpan(0));
cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
}
else
{
// auth failed, show 401
filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
filterContext.HttpContext.Response.End();
}
}
}
private void AuthorizeUser(AuthorizationContext filterContext, string user, string pass)
{
if (!System.Web.Security.Membership.Provider.ValidateUser(user, pass))
{
// Auth failed, show 401
filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
filterContext.HttpContext.Response.End();
}
else
{
var principal = new ApiPrincipal(new ApiIdentity(user), null);
filterContext.HttpContext.User = principal;
}
}
private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
{
validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment