global authorization not working - results in blank page rendered - asp.net-mvc-3

I am trying to implement a very basic login scheme for my MVC3 site. If I understand correctly, instead of adding the [Authorize] markup to each of my controller classes, I should be able to simply implement a global setting. To accomplish this, I have added the following into global.asax:
protected void Application_Start()
{
RegisterGlobalFilters(GlobalFilters.Filters);
}
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new AuthorizeAttribute());
}
and in my webconfig, I added:
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
The result is that the resulting page is totally blank. Looking at the url, it seems that mvc is redirecting to my login route as expected except the page empty. If I comment out the code in global.asax and just place the [Authorize] markup directly in each contoller, it works as expected.
As a workaround, I have implemented what I have read the MVC2 best practice to be, which was to create a BaseController:Controller class, add the [Authorize] markup to it, and then change the inherentences of all of my controllers to inheret from BaseController instead of Controller.
That seems to work well enough for now.
But why isn't the global.asax implementation working?

Let's see what's happening here:
You are navigating to /
Your global authorize attribute kicks in and since the user is not authenticated he is redirected to ~/Account/LogOn (as instructed in your web.config file) for authentication
Your global authorize attribute kicks in and since the user is not authenticated he is redirected to ~/Account/LogOn (as instructed in your web.config file) for authentication
Same as 3.
Same as 4.
...
I think you get the point. The LogOn action should be excluded from authentication otherwise the user can never get a chance to login to your web site.
Since you have applied the Authorize attribute globally this cannot be done. One possible way is to write a custom AuthorizeAttribute that will be applied globally and which will exclude this action from authentication.
So you could write a marker attribute:
public class AllowAnonymousAttribute : Attribute
{
}
and a global custom authorize attribute:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var exclude = ((AllowAnonymousAttribute[])filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), false)).Any();
if (!exclude)
{
base.OnAuthorization(filterContext);
}
}
}
that will be registered:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new MyAuthorizeAttribute());
}
Now all that's left for you is to decorate the controller actions that you want to be excluded from authentication with our marker attribute:
public class AccountController : Controller
{
[AllowAnonymous]
public ActionResult LogOn()
{
return View();
}
[AllowAnonymous]
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
...
}
}

Related

Handling expired oAuth token in asp.net mvc

I created a custom filter class which inherit ActionFilterAttribute
the method looks like below
public override void OnActionExecuting(HttpActionContext actionContext)
{
//my custom code
}
and my controller looks like below
[HttpPost]
[ActionName("Get")]
[Authorize]
[Filters.AuthorizeLogin()]
public List<BusinessEntities.Admin.Role> Get(Dictionary<string, string> Parameters)
{
//My api call
}
but the problem is whenever my token got expired my custom function (OnActionExecuting) did not execute,
I want to execute my custom function even after my token got expired.
and should I use [Authorize] filter when using [Filters.AuthorizeLogin()] filter in my api controller.

ASP.Net MVC 3 IF Statement outside Controller Action

I am developing an ASP.Net MVC 3 Web Application. I need to have my website secured with an SSL certificate, however, I only want this used when the application is on my live server, NOT on my test server.
Therefore, I setup an AppSetting in my Web Config like so
<appSettings>
<add key="SSL" value="false" />
</appSettings>
Then in my Account Controller I get this value (either True or False) and using the value, decide whether or not to set the RequiresHttps attribute on my LogOn Action. I would like to do something like so
public class AccountController : Controller
{
public string SSL = System.Configuration.ConfigurationManager.AppSettings["SSL"];
if (SSL.Equals("true"))
{
[RequireHttps]
}
public ActionResult LogOn()
{
return View();
}
}
But I know I can't put my IF statement where it currently is, however, hopefully you get the idea of what I am trying to achieve.
Does anyone have any suggestions as to how I can implement my idea?
Thanks.
Subclass the RequireHttpAttribute (note this code is changed from my original answer - this new version will be more efficient):
public class RequireHttpsIfEnabledAttribute : RequireHttpsAttribute
{
//this setting can't be changed without a recycle, so get it once and cache it.
private static readonly Lazy<bool> HttpsRequired = new Lazy<bool>(() => {
//if the AppSettings["SSL"] returns null you raise an exception if you do a
//.Equals on it - so do it on the constant instead. And make sure it's case
//insensitive!
return "true".Equals(System.Configuration.ConfigurationManager.AppSettings["SSL"],
StringComparison.OrdinalIgnoreCase);
});
public override void OnAuthorization(AuthorizationContext filterContext)
{
//calling the base will fire the HTTPS check. Not calling it will allow
//non-SSL requests through
if (HttpsRequired.Value)
base.OnAuthorization(filterContext);
}
}
Now you just decorate your controllers/actions as before - but with your new attribute:
[RequireHttpsIfEnabled]
public class AccountController : Controller
{
//....
}

AD Roles based Authorization in MVC3

In our MVC3 based Intranet app, one AD User may belong to many roles and during login, they will choose the role they want to login as. We are currently authenticating the user using the following approach: http://www.codeproject.com/KB/system/everythingInAD.aspx#35
Once the user is authenticated and found to belong to the role they are trying to login as, we would like to authorize access to specific Controllers and Actions based on their Role. We would prefer to use the Authorize attribute of the MVC.
Since we are not using any providers to autnenticate, can we still somehow use the Authorize attribute to restrict access?
Thanks!
Bala
You can use the Authorize attribute as long as your custom membership provider inherits from the asp.net MemberShipProvider class.
But if you decide to have an entirely new provide which doesn't inherit from asp.net MembershipProvider class than you can't use the Authorize attirbute.
#Pankaj is right but You can define you'r custom Attribute for exam: class MyAuthorizationAttribute : FilterAttribute, IAuthorizationFilter and override OnAuthorization method of it. then decorate each action with this custom attribute and calculate authorization in body of OnAuthorization. this is a sample:
public class MyAuthorizationAttribute : FilterAttribute, IAuthorizationFilter
{
public string _name;
public MyAuthorizationAttribute(string name)
{
this._name = curPerm.name;
}
public void OnAuthorization(AuthorizationContext filterContext)
{
// Calculate permissions...
if (!permit)
{
Exception e = new MethodAccessException("Access to partial denied!");
throw new Exception("Can't access via address bar!", e);
}
}
}
and use in action
[MyAuthorizationAttribute ("Add")]
public ActionResult Index()
{
ViewBag.Message = "About page";
return View();
}
Hope this useful.
Good luck.

Apply AuthorizeAttribute to a controller class and to action simultaneously

Is There one way to make a [Authorize] attibute be ignored in one action in a controller class that has a Authorize attribute?
[Authorize]
public class MyController : Controller
{
[Authorize(Users="?")]//I tried to do that and with "*", but unsuccessfuly,
public ActionResult PublicMethod()
{
//some code
}
public ActionResult PrivateMethod()
{
//some code
}
}
Just the PrivateMethod() should have authentication required, but it has been required too.
PS: I wouldn't like to make my custom authorize filter.
[]'s
You can use [AllowAnonymous]
[Authorize]
public class MyController : Controller
{
[AllowAnonymous]
public ActionResult PublicMethod()
{
//some code
}
public ActionResult PrivateMethod()
{
//some code
}
}
By default it's impossible - if you set [Authorize] for controller then only authenticated user can access to action.
or
You can try custom decisions: stackoverflow.
A solution is in this article: Securing your ASP.NET MVC 3 Application
The article talks about a white list approach where you decorate actions with a AllowAnonymous custom attribute. It requires that you extend AuthorizeAttribute and the OnAuthorization method to skip authorization checks of AllowAnonymous -actions. (The approach is credited to Levi, a security expert on the MVC team.)
public class MyController : Controller
{
[Authorize] //it will only work for the following action
public ActionResult PublicMethod()
{
//some code
}
public ActionResult PrivateMethod() //[Authorize] will not work for this action
{
//some code
}
}
Just for future reference This is now available to be done by the the [AllowAnonymous] attribute in ASP.NET MVC 4.
More Info

MVC SessionStateAttribute not working as Global Attribute

How do you setup SessionStateAttribute as a global filter in MVC3?
In my Global.asax I have this in the RegisterGlobalFilters method.
filters.Add(new SessionStateAttribute(SessionStateBehavior.Disabled));
And in my home controller I have this.
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
Session["Blend"] = "Will it blend?";
return View();
}
public ActionResult About()
{
return View();
}
}
But for some reason it still lets me use the Session. However if I decorate the HomeController class itself with the attribute, I get an error on the line utilizing the Session about a Object reference being null, which I'm guessing is intended if the Session is never created?
I am starting to wonder if there is something wrong with my project. I've been getting little problems like this one with standard behavior that are supposed to just work.
Anyone else had problems with things like this?
SessionStateAttribute is not an action filter, so you cannot add it as a global action filter. It's a special attribute which allows you to decorate your controllers with and have a more fine grained control over the session mode per controller.
To disable the session globally for the entire application put the following in your web.config:
<sessionState mode="Off" />

Resources