ASP.NET MVC3 - Most Appropriate Way to Store IsAdmin information - c#

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

Related

change loginpath for specific user, ASP.Net, webforms

I recently started working on a site that another developer built (who is not within the company anymore, so can't ask him)
On the site there is several separate accounttypes for users, so when a user logs in, the user comes to one of two specified login-start pages.
Some users have two accounttypes. When that's the case I want to make a dropdownlist that holds both startpage-options (let's call them a, and b)
If they choose option a) from the ddl, the a-startpage will be that users permanent startpage until the user changes it to b, then b will be that specific users permanent startpage.
the project is made with C#, ASP.NET, with Webforms, MS SQL.
any suggestions that might lead me in the right direction is much appreciated
/S
there are at least 2 possible solutions that require little effort:
a cookie on the user's system: when accessing the system for the
first time (or after a system change or a browser's cookies clearing)
the application takes the user to the dropdown page and let the user choose the
preferred login-start page. on subsequent accesses the choice is read from the cookie and then the user is forwarded to the expected page. the biggest advantage IMHO is that no changes to the backend structure are required and the changes on the fronted are minimal.BEWARE: do not trust what you get
reading the cookie and always double check that the page suggested
by the cookie is actually allowed for the user.
an attribute of the user: the user choice is saved in the user's profile and read on subsequent accesses.this approach requires some change in the backend because a new attribute must be added to the user entity and maybe also the tools (stored procedure, method, whatever) needed to interact with that new attribute have to be created.this solution requires less or no checks/validation because the information is stored server side so you can redirect 'blindly' to the login-start page.
there is not a 'right' solution because it mainly depends on what you are allowed to do and your skills.are you allwed to alter the backend's structure? what you know better, backend or frontend development?which one is easier for you to change? is there any policy/guideline to follow while developing that favor one of these approaches?
So in the end i solved it like this.
Firstly i created an int(allows null) column called "changesite" in the db (member/user)table so i could use the members id.
Then i connected it to the dropdownlist where the members/users can choose their startpage (in my case i made the ddl only visible to the members if they are the type of user that has the both user accounts).
if the user chooses the first option a 1 got saved in the db, and for the second option a 2. (This method could be used with any number of startpages you might have).
Then in .cs file were users got redirected to their designated startpage it was as simple as creating an if, else-statement, with the value from changesite as identifier.
Basically if the value from column changesite == null, do nothing. If changesite == 1 redirect to the first startpage and else redirect to the second startpage.
A big thx to Paolo for his inputs.

Hide Web Page From Public - WebMatrix 3

I am using C# Razor in order to make a social network. There are wepages that contain sensible data and I don't want someone to go to that url and see it. Not even by going to the Inspect Element and open it through there. So is there a way to warn the user that "This web page is not allowed"?
You have to implement authentication and authorization in order to control who can actually access any given route in an mvc application. I can only recommend that you start by reading the official site www.asp.net/mvc/overview/security about authorization and authentication.
With the proper authentication/authorization the server will simply not send any data, or you could redirect to a specific "not allowed page"
I agree with Louis, you should get this book here which helped me a ton. http://www.apress.com/9781430257523
The literal answer you are looking for concerns the use of authorization attributes you place above controller actions or controllers themselves. So an action might look like this
[Authorize]
public ActionResult UserAccount(Guid id){...}
By setting up authentication using ASP.Net Identity you will be able to automatically redirect visitors who are not logged in to another page etc.
Also if you need to make sure that the current logged in user is not going to (for example) another user's personal page (account settings?) you would do a simple check on the server side to prevent this. Something like so (Pseudo code)
if(User.Identity.GetUserId() != account.OwningUserId)
return RedirectToAction("404", "Shared");

Form authentication - Need event that should execute only once after form authentication happens

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.

securing an mvc application using subdomains

I have an mvc application that I allow businesses to log in using
https://storea.mydomain.com https://storeb.mydomain.com etc etc
Each of the businesses has users created and I have a table that matches business ID to EmployeeId. I am trying to lock the application down so an authenticated user of businessA cant access information from BusinessB.
Where is the best place for me to be checking the user is allowed to access the subdomain? Do I override the OnActionExecuted action checking what the subdomain is then look at a session value to see if they match, if different log them out.
Or this there a more elegant way to do this?
Suggestions and advise on best practices would be great! thank you
A custom Authorize attribute seems a good place to perform this. You could override the AuthorizeCore method where you will have access to the HttpContext and you will be able to perform the custom authorization logic based on the subdomain.
As I understand it, your MVC application uses a single database to store the information for all the businesses you have. This is why you'd be worried about Bussines A accesing Bussines B information.
So for me, your database is the place to check which information can access each user depending on the business they belong to.
I think you don't even need to use subdomains for this.
In cases like these I use the repository pattern and in every query/data access you ensure you pass in a where clause that contains the business id.
ex:
select * from orders where orderid=#orderId and companyID=#companyId
It is very important to do this on the query as you want data rules in place to prevent improper querying. Doing this on an Authorize attribute for example doesn't guarantee someone hasn't tampered with data to load another company's information.
In addition I have the http://mvcsecurity.codeplex.com/ extensions to help secure ids stored on pages to help prevent tampering.

umbraco authentication

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

Categories

Resources