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
Related
Hi I’m learning Blazor and I’m creating a backend & frontend app ( Blazor web assembly)
It works well, but my question is related to security.
I have user, business customer, and invoice. It's a very simple app
And user Id is a GUID and the others (business customer and invoice) are int & sequential (increment by 1 like 1,2, 3 and …)
Each user can not see the other user’s data and must not has access to them
this app has 2 parts, an API backend, and a Blazor frontend.
lets add some data like :
And End users can use the API only too without using frontend
I have in Invoice Repository:
Task<Invoice> GetInvoicesListAsync(int businessId);
and after verification users can access its invoices List
if we have a verified enduser like “Alex” (in the second row pf user table), can be retrieve the data that its not belong to him
Because BusinessId is sequential and when he knows his business Id is 99 , he can retrieve invoices for business 100,101,102 and … just with some trying
like :
var lst = await GetInvoicesListAsync(101);
my questions are:
1- How we can stop that? Do I need to enforce enduser to enter UserId as well for security into the API params like this :
Task<Invoice> GetInvoicesListAsync(Guid userId, int businessId);
2- If I add userId then is that has impact on the performance? because in this case I need to do Inner join with user table too and if we have complex database then it has big impact on the performance
3- what is your advice
thanks
Answers as point list:
No, you don't. The method GetInvoicesListAsync(int businessId) is good enough from a security point of view. You need to extract the list of business per user and check if the requested business is in the list, or more simply add a where / join condition filtering the invoices on the businesses of the user.
inner join is not a problem if you have the right indexes. Use your DB explain query plan to verify that your query is using index and do not execute any full table scan
when your user call the API you need to verify the user (valid token or cookie) and to obtain teh list of the business associated, so you don't need to receive this info from the API parameters. This is the biggest concern from a security point of view. The rule for secure API is "hey API, what's my name?"
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.
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.
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.
I want to verify that the user email is valid and turn this email into his id in my system.
Yet I don't know how to make a link in the mail, that activates the account like(facebook and others
) and I don't really understand what happens when the link is selected.
I thought of generating a key like "sdklbsdgk4493" to enter once- so that guessing is hard, yet for many people copy and paste is not trivial and I may annoy them with this solution.
Any thoughts or ideas?
p.s: I'm working in c# so if it can be done with c#... it will be great :)
Thanks Asaf
When you insert a new user in the Database, their status should be "Deactivated" and you insert a "GUID" you generate alongside. You send them a link to your activation Page which would contain this GUID in the Query String. It will look like this:
www.YourSite.com/Activation.aspx?GUID=jdfhg43h98234
In the Activation.aspx page, you take this GUID from the Query String and compare it to the one you have in the Database. You then activate the Account having that GUID.
Create the user
Generate a unique string for the user
Have a Table that stores the unique string, the user Id ,a boolean that holds whether it got activated or not, the generation date, the expiration date and if you have different uses for these activation strings, the type(link to another table)
Now within the email you should get the string and write it within the email along with a link to the page you're going to use for validation such as whatever.com/verify.aspx?activationString=hd3fd33fen342n43
Within this page you do a query search within the table that holds the keys and if its not already validated
You have your users table in the DB (or where ever it is that you store your list of users), just add a column stating if the user's mail is validated.
To the validation mail add a link that fires some PHP with a user-specific code (like it's index in the DB). The PHP will set the user's "validated" column to true, and it'll be done.
It's not as complicated as it may seem at first.
The idea is to create a random key, save it to the database connected to the useraccount, supplying a link to the users e-mail which could point to a webservice(or regular website) which takes the key as a querystring which will then activate the account connected to that specific key.