Add admin page without full fledged user management
Asked Answered
B

1

1

I am building a rather simple site with ASP.NET Core MVC 2.0 that is more or less an image gallery, just for me. I am not using any database so far. It is just a json file with metadata and the image files itself.

Now this site is supposed to get a hidden admin page where I (and only I) can upload new pictures.

What would be a simple but still secure way to add this admin page without having to introduce a full fledged user management to the site? I'd like to avoid to add a database and entity framework etc. to the site - there will only be one user.

In other words, what is a secure and simple way to add user management where there are is only one user that authenticates: Me, the admin.

Baneberry answered 13/9, 2017 at 21:45 Comment(3)
If strong security could be made simpler then it would already be that way. Simpler approaches to security have to accept higher levels of risk. Can you try to clarify what sort of risk you're willing to accept?Decompose
I am not willing to accept any risks. I'd just like to know if there is any simplification that can be done if there is always just one user. It kind of feels weird to introduce EF if I only have one username and one passwordhash to store. Maybe the app secrets can be used for that?Baneberry
app secrets in core aren't secure in any way. They are just to avoid secrets in source controlDecompose
D
1

Store a hashed version of your desired username/password in the appsettings.json and then rehash the values provided through the login screen and compare them.

Here's an example of how logging in could be accomplished. This bootstraps off of the default hasher present in Asp.Net Identity but you could use any hashing function.

You might want to create some other helpers too in case you want to reset the hashed password from your application versus having to go into the settings file.

appsettings.json

{
    ...
    "LoginCredentials": {
        "UsernameHash": "AQAAAAEAACcQAAAAENmv+riLvtTIa5wafXxzEX4rMSMXwVzG00q4jZKBI7Lx/oe2PFdqW1r521HBsL567g==",
        "PasswordHash": "AQAAAAEAACcQAAAAEKwwppiixEQM9QO7hOXcoXXgIvHKs9QHRz1k0lAZ3noVwID2lv+I+Dwc9OheqDGFBA=="
    }
}

Startup.cs

 public void ConfigureServices(IServiceCollection services)
 {
    //Assuming services.AddIdentity<...>(...) is not added as a service
    services.Configure<LoginCredentialOptions>(Configuration.GetSection("LoginCredentials"));
    services.AddTransient<IPasswordHasher<User>, PasswordHasher<User>>();
    ...
 }

LoginCredentialOptions.cs

public class LoginCredentialOptions
{
    public string UsernameHash { get; set; }

    public string PasswordHash { get; set; }
}

AccountController.cs

...
public async Task<IActionResult> Login([FromServices] IOptions<LoginCredentialOptions> loginCreds, LoginViewModel model, string returnUrl = null)
{
    if (ModelState.IsValid)
    {
        var passwordResult = passwordHasher.VerifyHashedPassword(null, loginCreds.Value.PasswordHash, model.Password);
        var usernameResult = passwordHasher.VerifyHashedPassword(null, loginCreds.Value.UsernameHash, model.Username);

        if (passwordResult == PasswordVerificationResult.Success &&
            usernameResult == PasswordVerificationResult.Success)
        {
            //Create identity cookie and sign in

            RedirectToAction(nameof(Index), "Home");
        }
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}
Decompose answered 16/9, 2017 at 20:50 Comment(2)
This looks good, I'd only need to find a better place to retrieve the user secrets from than from appsettings.json they probably shouldn't be stored there. This probably depdends on where I am going to host the app, on Azure I could use Key Vault.Baneberry
Since they are hashes you can store them in appsettings. If you're going to use azure key vault there's no point in hashing them.Decompose

© 2022 - 2024 — McMap. All rights reserved.