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.
Related
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");
}
I have multiple controllers in my project that do simple basic jobs like Get(int id), Get(), Insert(T t) and Edit(T t). To avoid code duplication I created a GenericController and then inherited all other controllers from this GenericController. Everything works very fine. But I run into issues when I want to implement different user roles on the same controller action when inherited. For example take a look of the code below:
public class GenericController<T>: Controller{
//other actions
[HttpGet]
public async Task<IEnumrable<T>> Get(){
//necessary action goes here
}
[HttpPost]
public async Task<IActionResult> Insert(T t){
//necessary action with t
}
}
[Authorize]
public class ProductController: GenericController<Product>{
//Get action is authorized to everyone
//Insert action is authorized to Manager only
}
[Authorize]
public class EmployeeController: GenericController<Employee>{
//Get action is authorized to everyone
//Insert action is authorized to Owner only
}
In the above snippet the Insert action, that is inherited from GenericController has different authorizations in both Product and Generic Controller.
I don't want to duplicate the code in the inherited controllers. But correct authorization is needed as well. Does anyone know the appropriate solution? Any help will be much appreciated.
Create authorize filter and find the controller and action like below. And then maintain the role.
string actionName = this.ControllerContext.RouteData.Values["action"].ToString();
string controllerName = this.ControllerContext.RouteData.Values["controller"].ToString();
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
Let's say I have WebApi Controller
[Authorize]
public class SomeApiController : ApiController
Controller action methods itself does not have any [Authorize] or [AllowAnonymous] attributes.
I want Authorize attribute to return 401 (Unauthorized) error if user has no roles - seems logical (if user had role and now doesn't have ANY - he shouldn't be allowed to perform action even though user is authenticated). I have looked to asp.net mvc webstack I have found the following code in Authorize attribute:
if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
{
return false;
}
So looks like if we didn't passed roles authorize attribute just checks if user is authenticated. Setting each role in Roles list is not an option for me ( I mean [Authorize(Roles="role1,role2,...")]).
Therefore question - can I somehow achieve setting Authorize attribute to check if user has ANY role. Or it's better to write custom attribute inherited from above?
Create custom attribute like below:
public override void OnAuthorization(AuthorizationContext filterContext)
{
string[] userRoles = System.Web.Security.Roles.GetRolesForUser(filterContext.HttpContext.User.Identity.Name);
if (!userRoles.Any())
{
throw new HttpException(401, "Unauthorized");
}
base.HandleUnauthorizedRequest(filterContext);
}
}
Hope it helps
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()
}
}