Search code examples
c#entity-frameworkasp.net-coreauthentication

How can I customize IdentityUser model in .NET Core 8


I am trying to create an authentication module in NET 8. I was able to create a system where I could receive tokens and auth easily.

public class DbContext : IdentityDbContext<IdentityUser>
builder.Services.AddIdentityApiEndpoints<IdentityUser>()
    .AddEntityFrameworkStores<DbContext>();

How can I manage this endpoints? I did not create any controller. When I want to register, request model is like that

{
  "email": "string",
  "password": "string"
}

I want to add some personal information such as address, gender, firstname, lastname etc. Can I customize this IdentityModel?

Additionally another question,

When I log in, I see this response

{
  "tokenType": "Bearer",
  "accessToken": "\\an access token",
  "expiresIn": 3600,
  "refreshToken": "\\an refresh token"
}

How can I change value of expiresIn attribute? The default value is 3600.

I am expecting customize this model easily but when I search solutions on internet, I see every programmer creates authentication service from scratch. Instead of this solution, I wonder can I customize default model?


Solution

  • How can I manage this endpoints? I did not create any controller. When I want to register, request model is like that

    Well, you can introduce your own viewModel to do that. You would just create that model with two property and then define the controller with that viewModel. Let's have a look below:

    ViewModel:

    public class RegisterModel
    {
        [Required]
        public string Email { get; set; }
    
        [Required]
        public string Password { get; set; }
    }
    

    Controller:

    Now, use RegisterModel as your controller signature that you are going to pass while calling this endpoint. Let's have a look in practice:

    [ApiController]
    [Route("api/[controller]")]
    public class RegisterController : Controller
    {
        private readonly UserManager<ApplicationUser> _userManager;
    
        public RegisterController(UserManager<ApplicationUser> userManager)
        {
            _userManager = userManager;
        }
    
        [HttpPost("register")]
        public async Task<IActionResult> Register([FromBody] RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser
                {
                    UserName = model.Email,
                    Email = model.Email
                };
    
                var result = await _userManager.CreateAsync(user, model.Password);
    
                if (result.Succeeded)
                {
                    //If the User registration successful
                    //Here You can generate and return a JWT token here if needed
                    return Ok(new { Message = "Registration successful" });
                }
                else
                {
                    
                    return BadRequest(new { Errors = result.Errors });
                }
            }
    
           
            return BadRequest(new { Message = "Invalid registration data" });
        }
    }
    

    Note: I am doing for asp.net core MVC application using identity, if you need the JWT, I have commented in the code snippet you can return JWT as well.

    I want to add some personal information such as address, gender, firstname, lastname etc. Can I customize this IdentityModel?

    Yes, you can do that, all you need a new class which would override the IdentityUser class. You can do that as follwoing:

    public class ApplicationUser : IdentityUser
        {
            public string Address { get; set; }
            public string Gender { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
        }
    

    Db Context for using ApplicationUser:

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
        {
            public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
                : base(options)
            {
            }
        
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
            }
        
            public DbSet<ApplicationUser> ApplicationUsers  { get; set; }
            
        
        }
    

    How can I change value of expiresIn attribute? The default value is 3600.

    In order to do that, you would require to modify your SecurityTokenDescriptor class which has the property Expires and here you can set the value you want in DateTime format. You can see below:

    enter image description here

    Let's take a look, you can you do that:

    While you you authenticate user, then your responsibility is to either redirecct to the user in correct page or generate token. So when you would generate token just do as following:

    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(claims),
        Expires = DateTime.UtcNow.AddHours(2) // Set the time you need
       
    };
    
    var tokenHandler = new JwtSecurityTokenHandler();
    var securityToken = tokenHandler.CreateToken(tokenDescriptor);
    var token = tokenHandler.WriteToken(securityToken);
    

    Note: If you still remain any confusion please refer to our offical document for tokenDescriptor modifiation and cusomize IdentityModel