Merge branch 'Sec_14_Seguridad_ASP.NET/60_Interfaces_Login_Register' into dev
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CleanArchitecture.Application.Constants
|
||||
{
|
||||
public static class CustomClaimTypes
|
||||
{
|
||||
public const string Uid = "Uid";
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
public class AuthResponse
|
||||
{
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public string UserId { get; set; } = string.Empty;
|
||||
public string Username { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string Token { get; set; } = string.Empty;
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace CleanArchitecture.Application.Models.Identity
|
||||
public string Key { get; set; } = string.Empty;
|
||||
public string Issuer { get; set; } = string.Empty;
|
||||
public string Audience { get; set; } = string.Empty;
|
||||
public double DuracionInMinutes { get; set; }
|
||||
public double DurationInMinutes { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
using CleanArchitecture.Application.Constants;
|
||||
using CleanArchitecture.Application.Contracts.Identity;
|
||||
using CleanArchitecture.Application.Models.Identity;
|
||||
using CleanArchitecture.Identity.Models;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
|
||||
namespace CleanArchitecture.Identity.Services
|
||||
{
|
||||
public class AuthService : IAuthService
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> userManager;
|
||||
private readonly SignInManager<ApplicationUser> signInManager;
|
||||
private readonly JwtSettings jwtSettings;
|
||||
public AuthService(UserManager<ApplicationUser> _userManager, SignInManager<ApplicationUser> _signInManager, JwtSettings _jwtSettings)
|
||||
{
|
||||
userManager = _userManager;
|
||||
signInManager = _signInManager;
|
||||
jwtSettings = _jwtSettings;
|
||||
}
|
||||
|
||||
|
||||
public async Task<AuthResponse> Login(AuthRequest request)
|
||||
{
|
||||
var user = await userManager.FindByEmailAsync(request.Email);
|
||||
if (user == null)
|
||||
{
|
||||
throw new Exception($"User with email: {request.Email} does not exist");
|
||||
}
|
||||
|
||||
var result = await signInManager.CheckPasswordSignInAsync(user, request.Password, false);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
throw new Exception("Invalid Login Attempt");
|
||||
}
|
||||
var token = await GenerateToken(user);
|
||||
var authResponse = new AuthResponse
|
||||
{
|
||||
UserId = user.Id,
|
||||
Token = new JwtSecurityTokenHandler().WriteToken(token),
|
||||
Email = user.Email!,
|
||||
Username = user.UserName!
|
||||
};
|
||||
return authResponse;
|
||||
}
|
||||
|
||||
public async Task<RegistrationResponse> Register(RegistrationRequest request)
|
||||
{
|
||||
var existingUser = await userManager.FindByEmailAsync(request.Email);
|
||||
if (existingUser != null)
|
||||
{
|
||||
throw new Exception($"User with email: {request.Email} already exists");
|
||||
}
|
||||
var existingEmail = await userManager.FindByEmailAsync(request.Email);
|
||||
if (existingEmail != null)
|
||||
{
|
||||
throw new Exception($"Email: {request.Email} is already in use");
|
||||
}
|
||||
var newUser = new ApplicationUser
|
||||
{
|
||||
Nombre = request.Nombre,
|
||||
Apellidos = request.Apellidos,
|
||||
Email = request.Email,
|
||||
UserName = request.Username
|
||||
};
|
||||
var result = await userManager.CreateAsync(newUser, request.Password);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
var errors = string.Empty;
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
errors += $"{error.Description}, ";
|
||||
}
|
||||
throw new Exception($"User Registration has failed: {errors}");
|
||||
}
|
||||
var token = await GenerateToken(newUser);
|
||||
var registrationResponse = new RegistrationResponse
|
||||
{
|
||||
UserId = newUser.Id,
|
||||
Email = newUser.Email,
|
||||
Token = new JwtSecurityTokenHandler().WriteToken(token),
|
||||
Username = newUser.UserName
|
||||
};
|
||||
return registrationResponse;
|
||||
}
|
||||
|
||||
private async Task<JwtSecurityToken> GenerateToken(ApplicationUser user)
|
||||
{
|
||||
var userClaims = await userManager.GetClaimsAsync(user);
|
||||
var roles = await userManager.GetRolesAsync(user);
|
||||
var roleClaims = roles.Select(role => new Claim(ClaimTypes.Role, role));
|
||||
|
||||
var claims = new[]
|
||||
{
|
||||
new Claim(JwtRegisteredClaimNames.Sub, user.UserName!),
|
||||
new Claim(JwtRegisteredClaimNames.Email, user.Email!),
|
||||
new Claim(CustomClaimTypes.Uid, user.Id),
|
||||
}.Union(userClaims).Union(roleClaims);
|
||||
|
||||
var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.Key));
|
||||
var signingCredentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256);
|
||||
|
||||
var token = new JwtSecurityToken(
|
||||
issuer: jwtSettings.Issuer,
|
||||
audience: jwtSettings.Audience,
|
||||
claims: claims,
|
||||
notBefore: DateTime.UtcNow,
|
||||
expires: DateTime.UtcNow.AddMinutes(jwtSettings.DurationInMinutes),
|
||||
signingCredentials: signingCredentials);
|
||||
|
||||
return token;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user