From 995e5918b887a248803152aa8f36fdbfa5659baf Mon Sep 17 00:00:00 2001 From: HombreLaser Date: Mon, 14 Nov 2022 23:31:32 -0600 Subject: Añadido registro de usuarios y configuración de JWTs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Controllers/UsersController.cs | 53 ++++++++++++++++++++++++++++++++++++++++++ DTOs/UserDTO.cs | 9 +++++++ IdentityAPI.csproj | 3 +++ Program.cs | 42 ++++++++++++++++++++++++++++++++- appsettings.json | 3 ++- 5 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 Controllers/UsersController.cs create mode 100644 DTOs/UserDTO.cs diff --git a/Controllers/UsersController.cs b/Controllers/UsersController.cs new file mode 100644 index 0000000..52c9105 --- /dev/null +++ b/Controllers/UsersController.cs @@ -0,0 +1,53 @@ +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Authorization; +using Microsoft.IdentityModel.Tokens; +using System.IdentityModel.Tokens.Jwt; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System.Text; +using System.Security.Claims; +using IdentityAPI.Models; +using IdentityAPI.DTO; + +namespace IdentityAPI.Controllers { + [Route("api/users")] + [ApiController] + public class UsersController : ControllerBase { + private readonly ApplicationDbContext _context; + private readonly IConfiguration _configuration; + private readonly UserManager _manager; + + public UsersController(ApplicationDbContext context, IConfiguration configuration, UserManager manager) { + _context = context; + _configuration = configuration; + _manager = manager; + } + + [HttpPost("signup")] + public async Task PostUser(UserDTO data) { + var user = new IdentityUser { UserName = data.UserName, Email = data.Email }; + var result = await _manager.CreateAsync(user, data.Password); + + if(result.Succeeded) + return Ok(new { Token = GenerateToken(user) }); + + return StatusCode(422, new { error = "The provided user is invalid" }); + } + + private string GenerateToken(IdentityUser user) { + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"])); + var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + var expiration = DateTime.UtcNow.AddMinutes(30); + var issuer = _configuration["Jwt:Issuer"]; + var claims = new List { + new Claim("sid", user.Id), + new Claim("username", user.UserName), + new Claim("email", user.Email) + }; + var descriptor = new JwtSecurityToken(issuer: null, audience: null, claims: claims, expires: expiration, signingCredentials: creds); + + return new JwtSecurityTokenHandler().WriteToken(descriptor); + } + } +} diff --git a/DTOs/UserDTO.cs b/DTOs/UserDTO.cs new file mode 100644 index 0000000..9336817 --- /dev/null +++ b/DTOs/UserDTO.cs @@ -0,0 +1,9 @@ +namespace IdentityAPI.DTO { + public class UserDTO { + #nullable enable + public string? UserName { get; set; } + public string? Email { get; set; } + public string? Password { get; set; } + #nullable disable + } +} diff --git a/IdentityAPI.csproj b/IdentityAPI.csproj index 1e26281..0d8799f 100644 --- a/IdentityAPI.csproj +++ b/IdentityAPI.csproj @@ -7,8 +7,11 @@ + + + diff --git a/Program.cs b/Program.cs index 19b5970..28b00d9 100644 --- a/Program.cs +++ b/Program.cs @@ -1,5 +1,10 @@ using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.IdentityModel.Tokens; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; using IdentityAPI.Models; var builder = WebApplication.CreateBuilder(args); @@ -8,9 +13,42 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddDbContext(o => o.UseNpgsql(builder.Configuration.GetConnectionString("ApplicationDbContext"))); +builder.Services.AddIdentity() +// .AddRoles() + .AddEntityFrameworkStores(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); +// Autenticación con JSON web tokens. +builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(options => { + options.TokenValidationParameters = new TokenValidationParameters { + ValidateLifetime = true, + ValidateIssuer = true, + ValidIssuer = builder.Configuration["Jwt:Issuer"], + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) + }; +}); +builder.Services.Configure(options => +{ + // Password settings. + options.Password.RequireDigit = false; + options.Password.RequireLowercase = false; + options.Password.RequireNonAlphanumeric = false; + options.Password.RequireUppercase = false; + options.Password.RequiredLength = 6; + options.Password.RequiredUniqueChars = 0; + + // Lockout settings. + options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5); + options.Lockout.MaxFailedAccessAttempts = 5; + options.Lockout.AllowedForNewUsers = true; + + // User settings. + options.User.AllowedUserNameCharacters = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+"; + options.User.RequireUniqueEmail = false; +}); // Identity configuration. // builder.Services.Configure(options => { @@ -25,7 +63,9 @@ if (app.Environment.IsDevelopment()) app.UseSwaggerUI(); } -app.UseHttpsRedirection(); +// app.UseHttpsRedirection(); + +app.UseAuthentication(); app.UseAuthorization(); diff --git a/appsettings.json b/appsettings.json index 02401f4..4404596 100644 --- a/appsettings.json +++ b/appsettings.json @@ -9,7 +9,8 @@ "ApplicationDbContext": "Host=127.0.0.1;Database=identity;Username=luis" }, "Jwt": { - "Key": "3aa68fb64d638cd66a0485fce8fcdb49" + "Key": "3aa68fb64d638cd66a0485fce8fcdb49", + "Issuer": "jwtissuer.com" }, "AllowedHosts": "*" } -- cgit v1.2.3