简体   繁体   中英

How to manage authentication and authroization in .NET Core 2.0 with Identity & Entity Framework

Introduction

I've been working for the last couple of days on small pet-project with a goal of learning .NET Core 2.0 with Identity backed by Entity Framework Core. It is a typical "WebAPI" type project with cookie based authentication and claims based authorization. It is utilized by some client application (SPA).

Code

Authorization & Authentication flow is configured this way in Startup.cs

services
    .AddIdentity<ApplicationUser, IdentityRole> ()
    .AddEntityFrameworkStores<ApplicationDbContext> ()
    .AddDefaultTokenProviders ();

services
    .AddAuthentication (sharedOptions => {
        sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddCookie ();

My login controller action looks like this:

[HttpPost]
[Route ("login")]
public async Task<IActionResult> Login ([FromBody] LogInCredentialsModel credentials) {
    // Get User for given UserName
    var user = await userManager.Users.FirstOrDefaultAsync (p => p.UserName == credentials.UserName);

    //User not found
    if (user == default (ApplicationUser))
        return StatusCode (400);

    // Check if password is correct
    var result = await signInManager.PasswordSignInAsync (user, credentials.Password, true, false);

    if (result.Succeeded) {
        //Basic claims with Name and Email
        List<Claim> claims = new List<Claim> {
            new Claim (ClaimTypes.Name, user.UserName),
            new Claim (ClaimTypes.Email, user.Email)
        };

        var userRoles = await this.GetUserRoles (user); // Custom helper method to get list of user roles

        // Add Role claims
        foreach (var role in userRoles) {
            claims.Add (new Claim (ClaimTypes.Role, role));
        }

        ClaimsIdentity identity = new ClaimsIdentity (claims, CookieAuthenticationDefaults.AuthenticationScheme);
        ClaimsPrincipal principal = new ClaimsPrincipal (identity);

        // Sign in using cookie scheme
        await HttpContext.SignInAsync (CookieAuthenticationDefaults.AuthenticationScheme, principal, new AuthenticationProperties {
            IsPersistent = true,
        });

        return Ok ();
    } else {
        return StatusCode (400);
    }
}

Problems

  1. These claims will be stored in encrypted user cookie. This means, that if I remove some claim from user and he does not re-log, he will still have old claims assigned. How do I prevent that? Or did I misunderstand the design?
  2. User passes UserName and Password to login route which is then used to sign him in. In my code, I have to first find user with given UserName (1st db hit), then try to sigin in with password using SignInManager (2nd db hit), read roles (3rd db hit) to build ClaimsPrincipal and then use HttpContext.SignInAsync so user cookie with correct claims is created. I personally feel like I'm missing something and in the result my code is overcomplicated, also atleast one of the database queries could be saved here. How to improve this part?

The answers to both of your questions are pretty basic, so maybe you should spend some more time with the docs to get a better handle on this. That said:

  1. Yes. You are correct. When you change a claim, you should sign the user out as well. Then, you can choose to automatically sign them in again, without user intervention, or prompt the user to re-login (depending on your personal security preferences).

  2. Why are you doing all this manually? All you need is:

     var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false); 

    That automatically hashes the password, attempts to retrieve the user with that username (email address) and hashed password, and then creates a ClaimsPrincipal with all that information, if successful. One and done.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM