I am using the latest and greatest Identity 3.x that comes stock with MVC6 Core 1.0 when selecting 'Individual User Accounts'.
The requirements of my user auth is the following:
Users -> AspNetUsers
Roles -> AspNetRoles
UserRoles -> AspNetUserRoles
RoleFunctions -> I don't see a table for this in the Identity db structure
RoleFunctions are any kind of system function such as DeleteCustomers, AccessToCustomerPage, etc.
I am going to assume ASP.NET Identity doesn't support this extra step with Roles-Based authentication so I am going to have to create the table and functions involved myself. Is this true or is it all there for me and I'm just not seeing it?
Identity allows you to determine authorization based on a controller, or a specific action in the controller.
[Authorize]
public void controllermethod(param) {}
authorize will require authentication before this action or controller can be visited.
So, if you wanted to create an action that only the admin could perform (or any user role group you have created), above the controller method you would put
[Authorize(Roles="admin")]
public void controllerMethod(param) {}
Roles can accept a list of strings, like (Roles="Admin","Manager"), so you can put multiple roles in a single authorization claim.
You can also do this on the controller level, forcing every action in the controller to adhere to your authorization claims. Basically if you put it above the controller declaration every action will be affected, but you can whitelist a particular action with
[AllowAnonymous]
public void nosecuritycontrolleraction {}
I hope this is what you are looking for, and you can find better guides here:
http://www.asp.net/identity
UPDATE 1
For the DeleteCustomer example, I'm assuming you have some methods in a controller that handles the deletion of a customer object. Above those methods, put [Authorize(Roles="CustomerAdmin")] and then only the users with the customerAdmin role in UserRoles can use that action.
like:
[Authorize(Roles="CustomerAdmin")]
public ActionResult DeleteCustomer(string/int id){}
Related
Is good idea to get user identity in ASP.NET Web API controller constructor, for example:
public PagesController(PageValidator pageValidator, PageMapper pageMapper, PagesManager pagesManager, UsersManager usersManager)
:base(usersManager)
{
_pageValidator = pageValidator;
_pageMapper = pageMapper;
_pagesManager = pagesManager;
if (User.Identity.IsAuthenticated)
_pagesManager.UserId = usersManager.GetByEmail(User.Identity.Name).Id;
}
Is always User.Identity was correct populated before this call raise?
This has bitten me a few times. Depending on where/how you are performing your authentication, you need to be careful where you access your identity, particularly in controller constructors.
For example, whilst the controller action is invoked AFTER an IAuthenticationFilter is instantiated, the controller's constructor is called before AuthenticateAsync; meaning any authentication you do in AuthenticateAsync will not be available in your controller's constructor (like in your example).
I typically don't rely on things being available during controller construction (unless handled by DI). Instead access the identity as you need it in your controller actions.
If you are looking at making identity lookup easier (i.e. pulling in your user object based on the User.Identity.Name property) create a base controller class that has a property or method that does it for you, then have your controllers inherit from that...
public User AuthenticatedUser
{
get
{
if (User.Identity.IsAuthenticated)
{
return usersManager.GetByEmail(User.Identity.Name);
}
return null;
}
}
EDIT
See here for a detailed breakdown of the Web.API lifecycle, showing controller creation occurring prior to authentication.
Yes. You can use this property in Controller in any place. ASP.NET has request pipeline: (http://www.dotnetcurry.com/aspnet/888/aspnet-webapi-message-lifecycle).
As you can see Authorization is early stage step in request pipeline.
Controller creation is the latest stage.
I have an Spring MVC application which using the classic three layer: controller service and dao.
And the related models in the application contains User Department Project.
One user will belong to a department, and there may be a lot of projects belong to a certain department, and the departments are organized as a tree like structure, for example:
dep1
dep1-1
dep1-1-1
dep1-1-2
...
...
...
Now I have a controller to list the projects:
class ProjectController{
private ProjectService projectService;
#RequestMapping("/list")
public String list(#RequestParameter("depId") String depId){
projectService.list(depId);
return "list";
}
}
ProjectServiceImpl implements ProjectService{
ProjectDao projectDao;
public List<Department> list(String depId){
}
}
It seems that this is rather simple, however we have two problems:
1 The result filter.
According to the configuration, the department of the current user maybe(or not) be under consideration during the query operation, for example, when the parameter depId is dep1-1-1, and the current user belongs to dep1-1-2, then we should return null.
As said, this feature maybe closed at all at some situation.
2 The authentication.
The user authentication and management is served in another application which will deployed at the same domain with my application, you can think they are two different folder inside the /tomcat/webapps. We use cookie to share the user information:save a token for a user.
Which means for every request, I will have to get the token of the current user(if they have login) from the cookie, and then call the service provided by the other application to get the information like department and etc.
So where to do the department check, in controller or service? I am not sure if inject the HttpRequest to service is a good idea or not.
Also Since there are too many controllers and services related to this kind of operation, I want to avoid the duplicate codes everywhere.
Is there any better choices?
It may be overkill, but what you are asking for make me think to spring-security :
authentication : spring security could do it directly, but you can also implement a custom PreauthenticatedAuthenticationFilter that would use the cookie to get the user info and populates a Spring Security Authentication token. This part is easy and highly configurable.
result filter : extract from the spring security reference manual :
Spring Security supports filtering of collections and arrays and this can now be achieved using expressions. This is most commonly performed on the return value of a method. For example:
#PreAuthorize("hasRole('ROLE_USER')")
#PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
public List<Contact> getAll();
When using the #PostFilter annotation, Spring Security iterates through the returned collection and removes any elements for which the supplied expression is false
All this is implemented through Spring AOP so it is easy to add those annotations on service methods.
Spring Security integrates nicely in a Spring MVC application. The only problem is that a full configuration including domain object security is not really trivial ...
I'm currently developing an ASP.NET MVC4 application which have 3 roles: admin, manager and editor. The editors can CRUD articles in the system BUT the editors can only read, update or delete their OWN articles. I've seen I can control the access to the controller and action by adding:
[Authorize(Roles="editor")]
but it only restricts the role not the information.
If the editor A created the article 1 ONLY the editor A has access to that article.
No other role has access to the controller or the information.
What would be the best practice in order to restrict the access by role and by context?
It is not practical to create a custom AuthorizeAttribute to check whether a user is allowed to update a specific article.
Instead, you want to check that logic in controller (or business logic). You can see that approach in a lot of open source projects.
[HttpPost]
[Authorize(Roles="editor")]
[ValidateAntiForgeryToken]
public ActionResult Update(ArticleModel model)
{
if(IsUserAllowedToUpdate(userId, model.ArticleId))
{
// Update article
}
return View(model);
}
You could implement this in the core of your system, for example by having a field in your datastore, identifying creator and users with permission.
Then you could implement your own authorizeattribute like;
public class CustomAuthenticateAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
// your own business logic, for instance, check if the user is the
// creator of the requested resource (check a database field you
// have created to identify the creator etc...)
// if that goes well authorize using regular roles, below
return base.AuthorizeCore(httpContext);
}
}
You would then decorate your controller with
[AuthorizeAttribute(Role = "editors")]
My MVC application makes use of a User's Role in multiple places during individual page requests. My question is whether the default SqlRoleProvider caches the current User's Roles for the lifetime of a page-request?
For example, I make use of Roles in attributes on Controller methods:
[Authorize(Roles = "Admin")]
and custom code
if (user.IsInRole(MembershipRole.Admin))
{
// Do something
}
else if (user.IsInRole(MembershipRole.Printer))
{
// Do something else
}
If the Role Provider does not cache roles, is the best solution to write a custom Role Provider that inherits from the default one, and override the methods to get the Roles once and cache them for the Request duration? Can this be done in a way that both the Authorize attribute and my own code will make use of the cached roles?
(In case you were wondering, I don't want to use the cacheRolesInCookie web.config option to cache the roles in cookies).
Thanks in advance for any suggestions.
[Edit to include details triggered from Joe's answer]
I decompiled System.Web.Mvc.AuthorizeAttribute and the AuthorizeCore method calls the following method for each role to be checked:
httpContext.User.IsInRole
Then peering into System.Web.Security.RolePrincipal (which is what "User" is above) both the methods below do indeed use a cached copy of the User's roles (or populates the cache if empty):
public string[] GetRoles()
public bool IsInRole(string role)
The cache is stored as a field on User, so its lifetime is for the duration of the request.
The methods find the roles using:
Roles.Providers[this._ProviderName].GetRolesForUser(this.Identity.Name)
so will use whatever role provider you have chosen for the application (default or custom).
If you use a RoleProvider in an ASP.NET or ASP.NET MVC application, then HttpContext.User will reference a RolePrincipal which does cache roles for the lifetime of the request.
However, in a WCF service that uses ASP.NET roles:
<behavior ...>
<serviceAuthorization principalPermissionMode ="UseAspNetRoles"
roleProviderName ="MyRoleProvider" />
</behavior>
this is not true: instead HttpContext.User will reference the internal class System.ServiceModel.Security.RoleProviderPrincipal, which does not cache roles: instead it always calls RoleProvider.IsUserInRole.
The out-of-the-box RoleProviders don't do any caching, so this can result in repeated connections to the underlying data store. It seems like a deficiency to me: it would have been easy to cache the roles on first access.
is the best solution to write a custom Role Provider that inherits from the default one, and override the methods to get the Roles once and cache them for the Request duration?
Not necessary for ASP.NET or ASP.NET MVC, but could be envisaged for WCF. Caching for the Request duration will presumably use HttpContext.Items, so will introduce a dependency on the existence of HttpContext, but that's not necessarily a problem except for making unit testing harder.
Can this be done in a way that both the Authorize attribute and my own code will make use of the cached roles?
If you configure your custom RoleProvider in web.config there's nothing more you need to do so that the Authorize attribute will use it.
In rails I could do something like this to make sure a user is authenticated before accessing an action in the controller:
before_filter :checked_logged_in, :only => [:edit, :update]
I was wondering if ASP.NET MVC had something similar or if there was a framework out there that could essentially do something like the following:
For certain methods with actions that take a certain parameter, I want to point the action to a method, check to see if the user owns that object, and if so, proceed to the controller action. If not, I want to redirect him to another action where I can show him he has invalid credentials.
So basically I am looking for a sort of "before_filter." Anyone know of anything out there that can do this? Thanks!
They are called Action filters in ASP.Net MVC, you can read more here http://www.asp.net/mvc/tutorials/understanding-action-filters-cs.
Asp.net MVC comes with an Authorize filter to indicate actions that requiere the user to be authenticated.
Usage:
[Authorize]
public ActionResult Index()
{
}