I’m using the Forms Auth and ASP Universal Membership Provider in an MVC 3 Site. We’re persisting the cookie for user convenience.
FormsAuthentication.SetAuthCookie(model.UserName, true)
When we disable a user in the Membership provider like this:
memUser.IsApproved = model.IsActive;
provider.UpdateUser(memUser);
if they have the cookie they can still get in to the site. This is similar to what is described in this post:http://stackoverflow.com/questions/5825273/how-do-you-cancel-someones-persistent-cookie-if-their-membership-is-no-longer-v
We use Authorize attributes on our controllers, and I know that that is technically more Authorize than Authentication. But the certainly overloap so I’m trying to figure out what is the best MVC way to do a check that the user is not actually disabled? Custom AuthorizeAttribute that checks the user against the membership database? An obvious setting/method I’m missing with Forms auth to invalidate the ticket?
Update:
Here’s basically what I’m going with – we use a custom permission denied page which we we use to better inform user that they don’t have rights vs. they’re not logged in. And I added the IsApproved check. AuthorizeCore gets called when you put the attribute on a Controller or Action and if it returns false HandleUnauthorizedRequest is called.
public class CustomAuthorization : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated || !Membership.GetUser(filterContext.HttpContext.User.Identity.Name).IsApproved)
{
filterContext.Result = new HttpUnauthorizedResult();
// in the case that the user was authenticated, meaning he has a ticket,
// but is no longer approved we need to sign him out
FormsAuthentication.SignOut();
}
else
{
var permDeniedRouteVals = new System.Web.Routing.RouteValueDictionary() { { "controller", "MyErrorController" }, { "action", "MyPermissionDeniedAction" }, { "area", null } };
filterContext.Result = new RedirectToRouteResult(permDeniedRouteVals);
}
}
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
{
// since persisting ticket,
// adding this check for the case that the user is not active in the database any more
return base.AuthorizeCore(httpContext) && Membership.GetUser(httpContext.User.Identity.Name).IsApproved;
}
}
Usage:
[CustomAuthorization()]
public class MyController
Well, you’re going to have to check the database regardless, the only question is how you want to do that. Yes, you could create a custom authorize attribute, or you could write some code for the OnAuthorize override in ControllerBase, or you could do it in Application_AuthenticateRequest.. lots of ways you could do it, depends on what works best for you.
The best way, of course, would be to not use a persistent ticket if this is an issue for you.