I'm creating my first ASP.NET MVC 3 app and I have a problem with creating class instance based on user role.
I have a Class called Account and it contains information about user accounts and few methods which allow me to manipulate(update) user account information. For example ChangeNickName, AddToGroup, RemoveFromGroup, Ban and so on.
As you can see problem with these methods is that I dont want to allow anyone to use AddToGroup or Ban method but only user with specified role (i'm using ASP.NET default role implementation system)
So I wonder is there a way I could add attribute [Authorize(Roles = "Admin")] to my AddTogroupMethod just like I use it on Controller methods
I know that with proper implementation of controllers I dont need something like this but I want to make sure that I dont allow anyone to make instance of class (or use specified methods by accident) if user is not part of specified role.
So for example if I by accident add access to AddToGroup method in user controller I would still be able to prevent them from exploiting bug because of attribute attached to this method
If I can't solve this problem with attributes is there a way to make VS to block me from debugging application if I make a call to AddToGroup method from xy class
If you have any ides how to make this working I'm open to suggestions
Than in advance
You should probably use the AuthorizeAttribute, however you can check the role of a current user in code using Roles.UserIsInRole.
There's a little info on this in MVC here (the assembly seems to have changed between 3.5/4.0):
asp.net mvc -> Roles.IsUserInRole(username,role)
Related
I'll make this post short and get straight to the seriousness of the situation. Our application has the concept of "Organizations" which are comprised of "Members". We recently found a huge security flaw in our application. If a Member that does not belong to a specific Organization (but is logged into the application) gets access to a URL for any of that Organization's pages, he/she can access that page.
Is there something built into .NET Core 3.0 or Web API that would allow us to stop users from being able to access Organization pages that user is not a Member of? The only way I can think to do it is check if the Member (based on their MemberId) belongs to the Organization (based on OrganizationId). However, that check would have to be added to every single API controller. There has to be a better way! Any help is appreciated...
Decided that I am going to:
1) Create a custom exception
2) Throw it in a base repo class that all of my derived classes are inheriting from
3) Propagate it up and catch it at the base controller class using an ActionFilter
4) Return 403 (w/ custom exception error message) to user (Angular)
5) Have the Angular HTTP interceptor handle the error message, meaning show to user
If anyone has a better idea please let me know.
This question already has answers here:
ASP.NET MVC3 Role and Permission Management -> With Runtime Permission Assignment
(4 answers)
Closed 9 years ago.
I know it is possible to annotate action methods to control access depending on roles like [Authorize(Roles = "Publisher")] but how can I achieve the same result if the access control information comes from database and can be changed anytime.
For example: Create action method can be accessed by Publisher but cannot be tomorrow because Admin disallowed Publisher to Create. This information will come from database and I have to somehow put appropriate annotation in runtime.
I hope I was able to convey my question properly. Any suggestion is appreciated.
Create action method can be accessed by Publisher but cannot be
tomorrow because Admin disallowed Publisher to Create. This
information will come from database and I have to somehow put
appropriate annotation in runtime.
I wouldn't solve the problem the way you mentioned. Changing Authorize attribute from "Publisher" to something else at runtime is not a good solution. Instead what you can do is to manage users in Publisher Role (for example remove/add users to that role at runtime). What I mean is, let Publisher Role have access to Create Action, but on the SQL side, you manage users who come under publisher role. In that way, there is no need for you to change Authorize attribute at runtime.
To maintain your roles in a SQL Database and use them, you can go for Custom Role Provider.
As I am working on Form Authentication in Asp.Net MVC, I want to know that -
Is there any event available in global.asax OR in base controller class which calls only ONCE when form authentication happens. (I want to add something in session only once and only when form authentication happens)
I tried with OnAuthorization and AuthorizeCore events of AuthorizeAttribute class.
Even I also tried with Application_OnAuthenticateRequest and Application_AuthorizeRequest events of Global.asax file..
BUT the issue is, all these events fires on every request and I want to execute somethings only once when authentication happens.
Could you please suggest me what is the best way to do this !?
Note: The authentication cookie is being set by another Asp.net MVC application which exist in same domain. (And I am accessing this application by submain - so I can access the auth cookie of parent application). BUT, when authentication happens to Application 1, I want to set some session variable in Application 2. (As my application 2 user is now authenticated and I want to add some information in session in application 2)
Thanks in advance!
When authentication occurs in application 1, add an additional cookie that will trigger setting the session variable in application 2. In the AuthorizeCore override of an AuthorizeAttribute in application 2, check for the presence of the cookie. If it exists, set the session variable and remove it.
You might also consider adding the info to the user data portion of the FormsAuthenticationTicket instead of storing it in session.
What you are asking is an application-specific event, and since the requirements and specifics of this can't be defined simply, there's no built-in event to handle this. So, you'll have to create this yourself.
Since you are using Forms Auth, you know exactly they authenticate, but I suspect you are interested in a way to communicate this to other modules or components in an loosely coupled, event-driven manner. I would suggest that you have a service interface defined in your business layer that represents your authentication service. You could then have your various components that need to notify (or be notified) of an authentication event talk to the authentication service directly, rather than try to push this through ASP.NET. My answer is rather vague because the info you've given about what you need to do in that event is not apparent.
For hell of it, we can consider how to push this through ASP.NET anyways. The class that is generated for your application, represented by Global.asax.cs, is like any class. You could conceivably add your own event to that class, and in IHttpModule (for example) that wish to subscribe to it, simply cast HttpApplication context parameter in the Init method to the specific type and attach the event as you normally would.
As you have found out, authentication executes on every request to verify whether or not the given user is allowed to view the given page. However, you will need to define a function somewhere which calls .SetAuthCookie() to authenticate the user (normally) on login. It is in this function where you should call your action.
To my knowledge, there is no OnAuthorized event. Perhaps there are in ASP.NET Forms, but in MVC things are little more manual and far more flexible.
If you are in a default ASP.NET MVC Internet application project, then open the AccountController in the \Controllers\ folder and find the Login method:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
{
// Add session data or trigger an event
return RedirectToLocal(returnUrl);
}
You should find something similar to the above. That is where you would add additional session data or any other one-time code you wish to execute when a user logs in.
The same concept applies even if you are not using the ASP.NET MVC Internet application. At some point, you will need a controller to handle the login POST. On a successful login is where you would execute your code.
In my ASP.NET MVC 3 application i have two types of users - regular users and admin users. Obviously the latter have greater privileges than the former. I have a page level authorization implementation in place, but for screen level items (show this button if admin, etc.) I would like to know what is the most appropriate solution to make a boolean IsAdmin flag available on all screens. I can think of a bunch of different methods cookies/session variables/httpcontext, but I'm wondering what is used with success in production. Any guidance is appreciated
Thanks in advance
JP
http://msdn.microsoft.com/en-us/library/system.web.httpcontext.user.aspx
HttpContext.User is of type IPrincipal, which has one method IsInRole. If you are using FormsAuthentication you'll get this for free. HttpContext.User will be available directly from any view
The ViewBag seems an easy fit.
ViewBag.UserIsAdmin = somevalue;
That's available to every view and is meant to be used for View data that isn't part of the model.
The only downside is that you need to populate it every request on views that need it, but you can actually do that in a Base controller's Initialization method if it's a global thing.
As for how to store it between requests, not cookies. Those are easily forgable. You can use a session to store it between requests, or you can simply repopulate it every request if it's a fast request (and you can't use sessions) in your Base controller.
Do not use Session, because you have to check whether it is timeout or not. It's hard to code in many places (my experience).
You can use Form Authentication that leveraged by ASP.NET membership. Then you can safely use HttpContext.User.Identity to check user privilege
I have an existing community backend and I like to use Umbraco for my presentation layer. How can I implement login/logout with .Net forms authentication? (I don't want to use the Member functionality). I have different type of users that get's access to different type of pages. How can I control this? User control?
Umbraco uses the ASP.NET member / role provider model for it's membership system, and it's a pretty straightforward step to swap the default one out for your own implementation. I've done this in the past where I wanted to authenticate members against an Active Directory store but I can't imagine it being much more difficult to authenticate against a custom database.
The benefit from this is you get full integration with the Umbraco membership system, and by using a custom role provider, editors will be able to restrict pages using the built in page-editing facilities as opposed to you having to hook in your own security controls.
You should be able to create a simple membership provider by extending the UmbracoMembershipProvider class and overriding the ValidateUser method. I haven't done this myself, but I know of others who have.
To authenticate against a custom role provider, you'll need to create a class derived from RoleProvider. The methods you'll be interested in overriding are - IsUserInRole, FindUsersInRole, GetAllRoles and GetRolesForUser.
Here's a link to a Scott Guthrie blog post which has more information on the provider API than you'll ever need to know, including the source code for the default providers.
I've used two approaches on my umbraco sites. Both approaches include user controls for login and logout that are responsible for authenticating a user with a custom solution and clearing credentials respectively. I also add, for both approaches, an umbracoMembersOnly attribute to any document types that I want to protect.
In the first approach, I had each individual template check to see whether or not the user was restricted from access. To abstract this, I created a siteuser class with an isMember or isLoggedIn method that was available site-wide and could be called from either an XSLT or User Control macro. The benefit to this approach is that I could tailor custom messages on each template rather than merely providing the same access denied page.
The second approach - which is the one I favor now - if to create a Permissions macro that is responsible for checking the user's right to access any page (i.e. checks for an umbracoMembersOnly attribute and, if true, checks for a session variable). This macro gets included in the master template, and so executes on every template. If the user doesn't have permission to access the current page, I redirect to the same page but with an ?alttemplate=RestrictedPage or similar appended to the query string. (Make sure that your Permissions macro checks for an alttemplate=RestrictedPage in the query string, or you'll end up in an infinite loop of redirects.)
You can checkout http://osMemberControls.codeplex.com