How to lock/unlock a user in MVC SimpleMembership - c#

In SimpleMembership there isn't any column in the database for a user to be locked/unlocked.
I basically need my administrator to enable or disable any user in my application.
Is there any alternatives to that?

I find it easiest to use Roles to do this. Have a ActiveUser role and tag your controllers or actions with a Authorize attribute.
[Authorize(Roles = "ActiveUser")]
Then some simple admin to add or remove users from the role to unlock and lock their access to everything protected with that roles attribute.
Roles.AddUserToRole(user.Username, "ActiveUser");
Roles.RemoveUserFromRole(user.Username, "ActiveUser");

Probably not the "approved" way of doing things, but this is how I do it.
There is a field within the webpages_Membership table called IsConfirmed. Typically, this is for when you want a 2-stage registeration process: sign-up then activate via a link within an email. By nature though, this field has the same affect as IsApproved within the former aspnet_Membership table: if set to true, a user can login; if false they can't. So I just use plain old SQL to set to true or false:
// If using EntityFramework
// 1. Setup my params
var params = new List<SqlParameter>() {
new SqlParameter("#UserID", 1),
new SqlParameter("#Activate", true) // or false
};
SqlParameter[] paramArray = params.ToArray();
// 2. Update the database
myDbContext.Database.ExecuteSqlCommand("UPDATE webpages_Membership SET IsConfirmed = #Activate WHERE UserId = #UserID", paramArray);

I haven't tried simplemembership yet, but this sound great for some of the small projects I am working on. Here are some options:
Option 1: Add a custom field to the table like shown here - http://www.dwdmbi.com/2012/10/adding-custom-fields-to-vs2012-mvc4.html
Option 2 Create a new table with a foreign key back to User. Do an additional check on this value.
Either way your are going to something extra for the check. You can customize the 'Authorize' attribute to include your check (instructions here - Override Authorize Attribute in ASP.NET MVC).

try this approach. It uses IsApproved rather than the IsLockedOut. If your implementation does not already use IsAproved, this would be a good solution.
MembershipUser user = Membership.GetUser(username);
user.IsApproved = false;
Membership.UpdateUser(user);
This is not exactly locking the user. Technically this call is taking approved status from the user and leaving them unable to log-in.

I dont know the technology you are using but either you have to give column in the table with lock unlock as you specified or siply add one table in the database(Say tlbDisable) where you can delete the entries in original table and insert it in new table(tlbDisable).
When you again want to enable that user then simple delete the entry from tlbDisable and insert it into original user table.

Related

Preventing unintended CRUD actions in mvc

To give some context on what I know. I learn some time ago from this tutorial even when you set a field from your model READ ONLY on the View how easy is use tools like fiddler to alter the POST data and change the value.
What you do in this case is use Model Binding to specify the list of fields you want Edit and ignore the rest
[HttpPost]
[ActionName("Edit")]
public ActionResult Edit_Post(int id)
{
EmployeeBusinessLayer employeeBusinessLayer = new EmployeeBusinessLayer();
Employee employee = employeeBusinessLayer.Employees.Single(x => x.ID == id);
UpdateModel(employee, new string[] { "ID", "Gender", "City", "DateOfBirth" });
^^^ Name isnt updated
if (ModelState.IsValid)
{
employeeBusinessLayer.SaveEmployee(employee);
return RedirectToAction("Index");
}
return View(employee);
}
Now I learn about Authentication using AspNet.Identity.
Can check if user isn't authenticated to send him to the Login page.
If user belong to certain Role, I can show personalized menus.
Or check the list of contacts for the user and show only those.
But even if you filter the list of contacts based on the user_id before create the view you can access the actions EDIT and DELETE using links like this.
http://MVCDemo/Employee/Edit/1
http://MVCDemo/Employee/Delete/1
And as long you are authenticated, you can change other users data.
So, how you integrate authentication with CRUD actions to avoid unintended actions?
Seem to me to solve this situation I have to apply something similar to the Model Binding example. When get and Edit or Delete post request, first get the Employee from the DB using the id and compare if belong to the current user.
But that create a lot of repeats code across all the functions.
So what is the right way to handle this?
EDIT
To try to make it clear. Lets assume I have an address book application. Each user have contacts:
contact_id user_id name phone ....
1 1 A
2 1 B
3 1 C
4 2 D
5 2 E
6 2 F
The action to show contacts use authenticated user_id to filter the contacts before send it to the view.
Then you have an Edit/Delete actions where you get contact_id and process to Update/Delete. Even when both users have permission to these actions they shouldn't be able to affect other users contacts. But as I explain is very easy change the page using a tool like fiddler.
I can only speak from personal experience but I don't know any MVC features for managing this for you; I've only ever taken the approach you outline of retrieving the data model from the database and explicitly writing the logic to check if the current user has permissions to modify this resource, returning a 401 error if not.
You can compare the incoming request userid with the userid you have in the session, encrypted cookie or web tokens like jwt which ever you use.
Usually if i have load balancer i use encrypted cookie where i store the logged in user's id and compare it with the id i am getting from the request. if both match, update/delete profile else return Unauthorized.
Same can be done in case of Session or tokens as well.

Assign user based on another table in asp.net mvc4

I'm not even sure how to search for this question, so forgive me if I'm asking a duplicate question and would be grateful for any redirection needed.
I have data (Account Number, Password, Internal Y/N) that is being submitted to an Account Table from Navision. I want to use this data to automatically create a user in the UserProfile table (Username = Account Number, Password = Password) and assign that user to the Admin role if Internal = Y and DealerAdmin if Internal = N.
The data will continue to be maintained for Account numbers in Navision, but the DealerAdmin can add additional users from the website. Is this possible? If so, please provide any pointers to tutorials as to where to start? I presume it's a simple SQL statement. Where do I add this code in MVC so that it gets updated every time there's new data in the Account Table?
If you are using SQL why not use a trigger to create a new record in your User UserProfile when your conditions are met?
If this does not work for you can take a look at the post below and call your proc to move the data over if needed.
ASP.NET MVC 4 intercept all incoming requests

Get all roles of any user (yes, not currently logged one)

In an MVC app, administrator has a CRUD controller for managing users. Now, the functionality of the edit part needs to be extended and it involves adding a number role dependent tabs. They depend on the role of the viewed user, rather than on roles of the administrator who is viewing them. The easiest way for achieving this, would be getting all roles of that user as a array of strings (or similar), but how do I actually go about obtain those.
Is there a preferred method of getting all roles of a single user in SimpleMembership (based on his UserId) or do I just have to patch up a stored function in the database and pull those through it?
Writing the function is not a big deal, but this problem doesn't sound like something I should have to make workarounds for.
Use the Roles.GetRolesForUser() method https://msdn.microsoft.com/en-us/library/8h930x07(v=vs.110).aspx
string[] rolesArray = Roles.GetRolesForUser("username");
With the string being the User Name of the user as contained in the aspnetdb.
If you want to find by using a guid, you could try the following:
Guid userId; // ID of user - you can populate this somehow
MembershipUser memUser = Membership.GetUser(userId);
string[] roles = Roles.GetRolesForUser(memUser.UserName);
Here is the stored procedure I mentioned in the question:
CREATE FUNCTION GetUserRoles
(
#UserId int
)
RETURNS TABLE
AS
RETURN
(
SELECT
r.RoleName
FROM
dbo.webpages_UsersInRoles uir
JOIN dbo.webpages_Roles r ON (r.RoleId = uir.RoleId)
WHERE
uir.UserId = #UserId
)
GO
The only reason to go with this instead than the answer by user1666620, would be if you wanted to skip one unnecessary query to the DB. The preferred method to use this solution would be to add this function to your dbml (or it's EF equivalent). Obviously this first needs to be added in the database.

MembershipCreateUserException: The username is already in use

I've created the simple membership tables myself so that I have the ability to update the username field(can't do this if you just let it autocreate it for you).
var confirmationToken = WebSecurity.CreateUserAndAccount(model.UserName, Request["Password"], new { NameFirst = model.NameFirst, NameLast = model.NameLast, ContactId = newContact.ContactId },true);
When I run this line of code I keep getting the error message that the Username already exists. What is weird is that there is no username in the table with the same name and it does it for every registration. It has something to do with me creating the tables myself probably but I can't see where it's having this problem.
It does add it to my UserProfile table (called it UserSecurity) but doesn't include the user in the membership table.
Edit: The line above is using the webpages_Membership table. I need it to use my UserMembership table instead.
Edit: The line above is using the webpages_Membership table. I need it to use my UserMembership table instead.
If you want Simple Membership Provider to use a different table than the default one you need to change the table that WebSecurity.InitializeDatabaseConnection points to.
In solution explorer, go to Filters -> InitializeSimpleMembershipAttribute.cs and use this instead:
WebSecurity.InitializeDatabaseConnection("MyContext", "TableToPointTo",
"UserIdColumn", "UserNameColumn", autoCreateTables: true);

Adding a new field or adding a new value?

If i have a field in my db which clarify the type of the application .
takes two values 0 or 1
0 for web app and 1 for win app
and now there is some requirement in my business:
There are some win applications available to all users and some of
them belong to specific users .
What 's the best solution to handle this case .
adding new field to state whether it's public or private
or just adding new value to the same field say 2 to state it's private win app
If you haven't already it would probably be best to slip in a user, role, permission based security model to the database/system, thereby giving you the ability to specify a group of users that have access to a particular application, whether it be web or windows based
I'd say add a new column next to your AppId called PublicIndicatior
Oh and be sure to have a lookup table so people can see what 0 or 1 means, and foreign key it to your data table
Lookup Table:
AppTypeId, AppTypeDescription
0, WebApp
1, WinApp
Data Table:
Id, AppTypeId, PublicIndicator
1,0,1
etc
As Pope suggested above (I +1 him), the best scenario is to add in a new user table (or tables for roles etc if possible) and then link to that through either a new foreign key, or using the appid (assuming it is on your table and unique). Then when the boss comes back 3 weeks later and say, "that's great, but now can we restrict App99 to just the Accounts Dept" you are not going back to the drawing board.

Categories

Resources