1
votes

I have a question that is more high-level rather than syntax.

In a nutshell, I'm building an Asp.Net Core web application (using MVC, using the built-in user authentication).

I'm extending the existing Identity entities to add properties that we need (that don't already exist in the Identity/ApplicationUser objects).

Ultimately, I need to have the ability where an admin can/will go into a page (view) to set up new users or another page (view) where the admin can modify any of the properties (except password/login) for an existing user.

Now that I'm neck-deep in trying to get this working (I modified the generated Register view to use as the "set up new users" one and have all of that working), and I'm now working on the Edit view, and I'm realizing I may have gone down the wrong path.

Going this way, I'm concerned that I may need to either figure out a way to have an Edit view that does NOT overwrite the encrypted password, or require the admin to change the user's password any time that they need to change something else (such as changing their department, or granting them access to portions of the site, for example).

So now I'm wondering if there was a better way I should have gone to accomplish this.

Suggestions? Recommendations?

It's not totally too late for me to start over on this portion of it.

1
Why would they need to modify the password? Take the password field out of that view and put it in a proper reset/change password viewCamilo Terevinto
That's what I meant - I don't WANT the admin to have the ability to modify one of the user's password (they'd instead use a "I Forgot My Password" view) - but I wasn't sure if I could code the controller such that it'd NOT overwrite the password with whatever default value was there any time the admin made another change.Scott
@Scott Does my answer help you?Ruard van Elburg
@RuardvanElburg Sorry, I meant to mark your answer as the answer a week ago (I actually thought I did - oops).Scott

1 Answers

1
votes

You'll need to make sure that you are not overposting. Using TryUpdateModel to update fields with posted values is a security best practice because it prevents overposting.

For example, suppose the Student entity includes a Secret property that this web page shouldn't update or add. Even if the app doesn't have a Secret field on the create/update Razor Page, a hacker could set the Secret value by overposting. A hacker could use a tool such as Fiddler, or write some JavaScript, to post a Secret form value. The original code doesn't limit the fields that the model binder uses when it creates a Student instance. Whatever value the hacker specified for the Secret form field is updated in the DB.

Example to prevent overposting using TryUpdateModel:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
        return Page();

    var emptyStudent = new Student();

    if (await TryUpdateModelAsync<Student>(
        emptyStudent,
        "student",   // Prefix for form value.
        s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate))
    {
        _context.Student.Add(emptyStudent);
        await _context.SaveChangesAsync();
        return RedirectToPage("./Index");
    }
    return null;
}

Personally I never use entity objects, I use ViewModels instead. And most certainly when it comes to Identity. First of all to keep concerns seperated. And as a benefit things will become a lot easier. While something as overposting is not likely to happen that way.

For admins you can use an alternative TryUpdateModel. But I wouldn't use CRUD for Identity. Instead use the existing functionality from UserManager, etc.