Make an exception on AuthorizeAttribute - c#

I have a controller with many actions. All should be accessible to certain users only except one action:
[Authorize(Roles = "Admin")]
public class SecretsController : Controller
{
[Authorize]
public ActionResult Index()
{
return View(...);
}
...
}
Even [Authorize (Roles = null)] doesn't work. The method attribute will be ignored! How could I get the exception for just one action? Like AllowAnonymous allows it but visible to logged in users?

You can use OverrideAuthorization attribute like I do in the code below :
[Authorize(Roles = "Admin")]
public class SecretsController : Controller
{
[OverrideAuthorization]
[Authorize()]
public ActionResult Index()
{
return View(...);
}
...
}
With [OverrideAuthorization] which came with ASP.Net MVC5 you tell your Index action to override/ignore the authorization rules defined at the controller level.
By doing this, all your actions defined in SecretsController are visible only to Admin role except Index action which will be visible only to authenticated user even if they are not in Admin role.

use the attribute AllowAnonymous
[Authorize(Roles = "Admin")]
public class SecretsController : Controller
{
[AllowAnonymous]
public ActionResult Index()
{
return View(...);
}
...
}
Edit
Since the question was edited right after my answer to precisely mention not wanting the anonymous option
Like AllowAnonymous allows it but visible to logged in users?
The best answer is now CodeNotFound's answer

Related

Limit UmbracoAuthorizedController to Umbraco Admin Users Only

I have create a new controller, inherited from the Umbraco.Web.Mvc.UmbracoAuthorizedController and trying to limit it to only logged in Umbraco Administrators.
My current solution displays the view for only logged in umbraco users, but I cannot filter for only admins.
Code:
I have a Composer and I set up the route config:
public class ApplicationEventComposer : IComposer
{
public void Compose(Composition composition)
{
RouteTable.Routes.MapRoute(
name: "ITTest",
url: "umbraco/backoffice/ITTest/{action}/{id}",
defaults: new { controller = "ITTest", action = "Index", id = UrlParameter.Optional }
);
composition.Register<ITTestController>(Lifetime.Request);
}
}
I have a controller:
public class ITTestController : Umbraco.Web.Mvc.UmbracoAuthorizedController
{
public ActionResult Index()
{
return View("/Views/ITTest/Index.cshtml");
}
}
I have tried to add different attributes to filter for only adminsitrators like:
[UmbracoAuthorize(Roles = "admin")]
[UmbracoApplicationAuthorize(Roles = "admin")]
[AdminUsersAuthorize]
And tried different roles like "admin", "administrator", "administrators", "Administrators" etc. but nothing seems to work.
(Side note: At the moment I am thinking about a workaround and overwrite the OnAuthorization event, but that would be more of a hack than a proper solution.)
Questions:
How can I filter the users using Umbraco roles?
What are the role names exactly? Are they the user group names or something else?
Update:
(I tried to improve the answer below, but it was rejected, so I will add my findings here)
The [Authorize(Roles = "admin")] one is working!
I was playing around with it. To make it work it still needs to be under "umbraco/backoffice", but it does not have to be a UmbracoAuthorizedController it seems to be working fine when it is (only) RenderMvcController
The built in role names are:
"admin"
"sensitiveData"
"translator"
"writer"
"editor"
For more info: https://our.umbraco.com/forum/using-umbraco-and-getting-started/99651-limit-umbracoauthorizedcontroller-to-umbraco-admin-users-only#comment-313527
The UmbracoAuthorizedController controller effectively just adds the UmbracoAuthorize attribute to your controller, but it seems this attribute ignores any roles you pass in, and just checks the visitor is an authenticated back-office user.
You can see this in detail in the AuthorizeCore method in:
https://github.com/umbraco/Umbraco-CMS/blob/853087a75044b814df458457dc9a1f778cc89749/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs
and the ValidateRequestAttempt method in:
https://github.com/umbraco/Umbraco-CMS/blob/853087a75044b814df458457dc9a1f778cc89749/src/Umbraco.Web/Security/WebSecurity.cs
This isn't what I would have expected!
To achieve what you require you could inherit from the Umbraco.Web.Mvc.UmbracoController controller and decorate it with a standard MVC Authorize attribute.
I've successfully tested the following in Umbraco 8.2.0:
public class ITTestController : Umbraco.Web.Mvc.UmbracoController
{
[Authorize(Roles = "someGroup")]
public ActionResult Index()
{
return View("/Views/ITTest/Index.cshtml");
}
}
where someGroup is the Umbraco group you wish to allow.
Umbraco documentation:
https://our.umbraco.com/documentation/Implementation/Controllers/
suggests you should use the Umbraco.Web.Mvc.UmbracoAuthorizeAttribute attribute, which I think you've tried, so I would just update the Roles to be Roles = "Administrators", so you have something like:
[UmbracoAuthorize(Roles = "Administrators")]
public ActionResult Index()
{
return View("/Views/ITTest/Index.cshtml");
}

Why the authorize attribute is not getting overridden on action?

I have this controller which should be only authorized to role= 1 but there is also an action inside it that needs to be authorized to both roles i.e. 1 and 2 so what I did is that I have authorized the controller to role 1 and then overridden the action to have 2 roles but that doesn't work, it's still only accessible to role 1.
why ?
[Authorize(Roles = "1")]
public class ServicesController : BaseController
{
// GET: Services
[OverrideAuthorization]
[Authorize(Roles="1,2")]
[HttpGet]
public JsonResult GetServices()
{
return Json(ServicesRepository.SelectServices(), JsonRequestBehavior.AllowGet);
}
}
Your code is correct. I guess you need to override another action too because it seems like you are not overriding the action that returns the view at first.
Override that action which gets called when you execute the controller.

C# mvc5 - Easy way to check if user is authenticated in each controller method

I have a controller that I only want authenticated users to be able to access. Do I have to put a check in each method in my controller to verify a user is authenticated, or is there another way to handle this? Can I use annotations to do this instead?
Example from my controller:
public ActionResult Index()
{
if (UserVerified())
{
...
}
return RedirectToAction("Login", "Account");
}
public ActionResult FacebookLogin()
{
if (UserVerified())
{
....
}
return RedirectToAction("Login", "Account");
}
private bool UserVerified()
{
if (User != null && User.Identity != null && User.Identity.IsAuthenticated)
{
return true;
}
return false;
}
You can use AuthorizeAttribute for it.
Put it to every action.
[Authorize]
public ActionResult Index()
{
}
[Authorize]
public ActionResult FacebookLogin()
{
}
It will do the whole work for you. It checks whether the currect user is authenticated. If he is authenticated - proceeds to the action, if he is not - returns to the home page.
You can also add this attribute to a controller. Then all actions will require authorization.
[Authorize]
public class HomeController
{
public ActionResult Index()
{
}
public ActionResult FacebookLogin()
{
}
}
Update: And, yes, as Kamil said. Read this article, please.
http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api
You spend some time now and will spend much less time having questions about ASP.NET authentication in future.
By the way, you don't need to check for
User != null && User.Identity != null
If you are using default authentication then you can be always sure that User.Identity is a proper object. You can access User.Identity.IsAuthenticated directly.
Using Authorize attribute is way to go (already answered here). In addition, if you may want to implement some other business rules or filtering checks, you can create a filter class inheriting from AuthorizeAttribute.
e.g.
public class CustomAuthorizeFilter: AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var isAuthorized = base.AuthorizeCore(httpContext);
if (!isAuthorized)
{
return false; //User not Authorized
}
else
{
//Check your conditions here
}
}
}
Then decorate your controller or Action as:
[CustomAuthorizeFilter]
public class SomeController
{
}
You can either user [Authorize] attribute which is inbuilt. Or you can develop your custom attribute for the same purpose.
You can start from here for your own attribute:
Create custom attribute
If you want to perform validation on each action method, then put that attribute on Controller level rather than each action method.
You can use [Authorize] attribute above controller methods.
Please follow this link
If you want the authentication rules to apply to all controller actions you can do this:
[someAuthAttribute]
public class HomeController : Controller
{
// pseudo
public ActionResult Index() {
return response;
}
public ActionResult FacebookLogin(){
return response;
}
}
Where Index() and FacebookLogin() will adhere to the authentication rules of [someAuthAttribute]. You can also use this "hierarchy" to apply more specific rules to your action methods. Like this:
[someAuthAttribute]
public class HomeController : Controller
{
// pseudo
public ActionResult Index() {
return response;
}
[someFBAuthAttribute]
public ActionResult FacebookLogin(){
return response;
}
}
You can inherit authorization from a base controller.
[Authorize(Roles = #"Domain\Group")]
public class BaseController : Controller
public class ChildController : BaseController

How to handle Login and Logout In MVC 4

What am doing in my application for authorization is that when a user log in one cookie will be created with the user's id there after in every action i l check the cookie and if its not null then proceeds otherwise redirects to log in page assuming the user is been logged out.
Is there any Good method in MVC so that I can avoid the check in every action. Or a good way for authorization.
You may use [Authorize] attribute:
It can't be use for every ActionResult:
[Authorize]
public ActionResult Index()
{
return View()
}
Or for controller. In that case you don't need apply attribute for every action:
[Authorize]
public class HomeController : Controller
{
public ActionResult Index()
{
return View()
}
}
If any action in controller with [Authorize] attribute allows nnonymous use, you may use [AllowAnonymous] attribute for it:
[Authorize]
public class HomeController : Controller
{
public ActionResult Index()
{
return View()
}
[AllowAnonymous]
public ActionResult Edit()
{
return View()
}
}

Protect entire website behind a login i.e. "Authorize" all Actions within all controllers

title pretty much says it all.
I have a website which will only run behind a login so I want to ensure that nothing can be accessed unless you're logged in. This includes ActionResults, JsonResults etc...
Currently, I have [Authorize] all over my controllers which is quite tedious and not very DRY :)
So can I protect the entire website with 1 magic line of code? (The login page will obviously need to be accessible)
Also, please note that I will still need to further protect some of the Actions to only be used by certain Users/Roles
If you have multiple controllers, then make a AuthorizeController from which you inherit your controllers that must be protected. Just set the [Authorize] attribute to the AuthorizeController:
[Authorize]
public class AuthorizeController: Controller
{
}
public class HomeController : AuthorizeController
{
...
}
// don't inherit AccountController from AuthorizeController
public class AccountController : Controller
{
public ActionResult Login()
{
...
}
}
If you are trying to secure an entire website, you could use a global filter:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new AuthorizeAttribute());
}
}
See here for more information http://visualstudiomagazine.com/blogs/tool-tracker/2013/06/authenticating-users-in-aspnet-mvc-4.aspx
Nevermind! I think I found it!
Placing [Authorize] above the Controller class seems to protect all actions, and is further customisable on a per-action basis. YES!
[Authorize]
public class SomeController : Controller
{
// All logged in users
public ActionResult Index()
{
...
}
[Authorize(Roles="Admin")] // Only Admins
public ActionResult Details()
{
...
}
}

Categories

Resources