How to persist extended Identity(Authentication) fields. net CORE 5.0

Asked

Viewed 101 times

1

I have a project in ASP.NET MVC CORE 5.0 .

What I want to do:

  • Retrieve the information dadAleatorio user logged in, in any controller to insert them in wheres and creates.
  • For example I want to register an item, and in it I put this dadAleatorio (logged user information)

With stretched fields I mean:

  • The Identity by default comes the predefined fields, but searching deep, I saw that it is possible to add more information to the logged in user

I created a basic authentication template using Identity:

public class AccountController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;


    public AccountController(UserManager<ApplicationUser> userManager,
                                SignInManager<ApplicationUser> signInManager)
    {
        _userManager = userManager;
        _signInManager = signInManager;
    }

    [HttpGet]
    public IActionResult Login(string returnUrl)
    {
        return View(new ViewModels.LoginViewModel()
        {
            ReturnUrl = returnUrl
        });
    }

    [HttpPost]
    public async Task<ActionResult> Login(ViewModels.LoginViewModel loginVM)
    {
        if (!ModelState.IsValid)
        {
            return View(loginVM);
        }

        var user = await _userManager.FindByNameAsync(loginVM.UserName);

        if (user != null)
        {
            var result = await _signInManager.PasswordSignInAsync(user, loginVM.Password, false, false);

            if (result.Succeeded)
            {
                //Verifica se a url é nula, e se ela é interna para evitar open redirect atacks
                if (!string.IsNullOrEmpty(loginVM.ReturnUrl) && Url.IsLocalUrl(loginVM.ReturnUrl))
                {
                    return LocalRedirect(loginVM.ReturnUrl);

                }
                
                return RedirectToAction("Index", "Home");
            }
        }
        ModelState.AddModelError("", "Usuário/Senha inválidos");
        return View(loginVM);
    }

    public IActionResult Register()
    {
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Register(ViewModels.LoginViewModel registroVM)
    {
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser() { UserName = registroVM.UserName };
            var result = await _userManager.CreateAsync(user, registroVM.Password);

            if (result.Succeeded)
            {
                return RedirectToAction("Index", "Home");
            }

            foreach (var error in result.Errors)
            {
                ModelState.AddModelError("", error.Description);
            }
        }
        return View(registroVM);
    }

    [HttpPost]
    public async Task<IActionResult> Logout()
    {
        await _signInManager.SignOutAsync();
        return RedirectToAction("Index", "Home");
    }
    [HttpGet]
    [AllowAnonymous]
    public IActionResult AccessDenied()
    {
        return View();
    }
}

I needed to add an extra column to the dbo.AspNetUsers. I inserted it via SQL because I am working with database first.

inserir a descrição da imagem aqui

I also created a class to accomplish this:

    public class ApplicationUser : IdentityUser
{
    [PersonalData]
    public int? dadoaleatorio { get; set; }

}

When injecting Identity anywhere in the project I use that Applicationuser and everything works smoothly. But at certain points of the project I need to use this "dataAleatorio" field to pass as a parameter when creating certain objects, or show certain tables. How to proceed?

Edit:

I was able to recover user data on any controller using:

var user = await _userManager.GetUserAsync(HttpContext.User);

How do I persist with this data?

  • Currently at each Reload or controller change there would be a query in the database
  • I know that the default Identity data is saved in cookies. It’s like make an extension of that too?
  • I don’t understand your question. The data field is allowing nulls in the bank and in the class not.

  • I corrected the null part. What I want to do is the following, when registering a precise item Insert this dateAleatorio. Which means we need to retrieve that information from the bank. I know that Identity does this with id, email, etc. I want to know if there is a way to do this with the field created or if I need to make a query

  • The concept of Identity is from the bank. If the column has the auto increment it will receive the value automatically. Depending on how you are inserting into the database, the insertion command already returns the modeling, in other cases you will have to do the query. For example: Entity Framework Core usually updates modeling after a Savechanges().

  • @M.Bertolazo I refer to the Native Authentication/Authorization API itself. NET https://docs.microsoft.com/pt-br/aspnet/core/security/authentication/identity?view=aspnetcore-5.0&tabs=visual-studio

  • @M.Bertolazo https://csharp-video-tutorials.blogspot.com/2019/06/extend-identityuser-in-aspnet-core.html I followed this tutorial to implement this. https://csharp-video-tutorials.blogspot.com/2019/06/extend-identityuser-in-aspnet-core.html

  • is basically just that. Even though database first, don’t need to create a Migrations to update the schemas? When you add Identity it does, even for the Identity model, via code first

  • This guy here userManager.Findbynameasync(loginVM.Username) does not return the identityuser? If it is, in theory I would caste it for an applicationuser and solve your problem...

  • @Lucasmiranda I was able to recover the user object using: var user = await _userManager.Getuserasync(Httpcontext.User); However this data is not persisted along with the rest of the Identity data (saved in cookies). That is to every page or call Reload in some controller it would search in the bank

  • @Ricardopunctual I confess that I got a bit confused. I had to enter the Identity SCRIPT manually due to some bugs already fixed. However, the model is coherent with the bank. I updated the question to the approach I was looking for. How to persist with this information during the session

Show 4 more comments

1 answer

0


To be able to persist the data customized (additional fields of the aspNetUser table) and use them anywhere in the code I did the following:

First I created a class that adds CLAIMS.

public class IdentityExtensions : UserClaimsPrincipalFactory<ApplicationUser>
{
    public IdentityExtensions(
        UserManager<ApplicationUser> userManager,
        IOptions<IdentityOptions> optionsAccessor)
            : base(userManager, optionsAccessor)
    {
    }

    protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
    {
        var identity = await base.GenerateClaimsAsync(user);
        identity.AddClaim(new Claim(type: "dadoAleatorio", value: user.dadoAleatorio.ToString()));

}

Once this is done, just go to Startup.Cs and add the class in configureServices:

services.AddIdentity<ApplicationUser, IdentityRole>()
         .AddEntityFrameworkStores<ApplicationContext>()
         .AddDefaultTokenProviders()
         .AddClaimsPrincipalFactory<IdentityExtensions>(); //ADICIONE ESSA LINHA

And finally just request this CLAIM where necessary

var LoggedUserDadoAleatorio = User.FindFirst("dadoAleatorio").Value;

Browser other questions tagged

You are not signed in. Login or sign up in order to post.