diff --git a/Newsbot.Collector.Api/Services/IdentityService.cs b/Newsbot.Collector.Api/Services/IdentityService.cs new file mode 100644 index 0000000..2955479 --- /dev/null +++ b/Newsbot.Collector.Api/Services/IdentityService.cs @@ -0,0 +1,114 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using Microsoft.AspNetCore.Identity; +using Microsoft.IdentityModel.Tokens; +using Newsbot.Collector.Api.Domain.Results; +using Newsbot.Collector.Domain.Models.Config; + +namespace Newsbot.Collector.Api.Services; + +public interface IIdentityService +{ + AuthenticationResult Register(string email, string password); + AuthenticationResult Login(string email, string password); +} + +public class IdentityService : IIdentityService +{ + private readonly UserManager _userManager; + private readonly JwtSettings _jwtSettings; + + public IdentityService(UserManager userManager, JwtSettings jwtSettings) + { + _userManager = userManager; + _jwtSettings = jwtSettings; + } + + public AuthenticationResult Register(string email, string password) + { + var userExists = _userManager.FindByEmailAsync(email); + userExists.Wait(); + + if (userExists.Result != null) + { + return new AuthenticationResult + { + ErrorMessage = new[] { "A user with this email address already exists" } + }; + } + + var newUser = new IdentityUser + { + UserName = email, + Email = email + }; + + var createdUser = _userManager.CreateAsync(newUser, password); + createdUser.Wait(); + + if (!createdUser.Result.Succeeded) + { + return new AuthenticationResult + { + ErrorMessage = new[] { createdUser.Result.Errors.Select(x => x.Description).ToString() } + }; + } + + return GenerateJwtToken(newUser); + } + + public AuthenticationResult Login(string email, string password) + { + var user =_userManager.FindByEmailAsync(email); + user.Wait(); + + if (user.Result == null) + { + return new AuthenticationResult + { + ErrorMessage = new[] { "User does not exist" } + }; + } + + var hasValidPassword = _userManager.CheckPasswordAsync(user.Result ?? new IdentityUser(), password); + hasValidPassword.Wait(); + + if (!hasValidPassword.Result) + { + return new AuthenticationResult() + { + ErrorMessage = new[] { "Password is invalid" } + }; + } + + return GenerateJwtToken(user.Result ?? new IdentityUser()); + } + + private AuthenticationResult GenerateJwtToken(IdentityUser user) + { + var tokenHandler = new JwtSecurityTokenHandler(); + var key = Encoding.ASCII.GetBytes(_jwtSettings.Secret ?? ""); + var tokenDescriptor = new SecurityTokenDescriptor + { + Subject = new ClaimsIdentity(new[] + { + new Claim(JwtRegisteredClaimNames.Sub, user.Email ?? ""), + new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), + new Claim(JwtRegisteredClaimNames.Email, user.Email ?? ""), + new Claim("id", user.Id) + }), + Expires = DateTime.UtcNow.AddHours(3), + SigningCredentials = + new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) + }; + + var token = tokenHandler.CreateToken(tokenDescriptor); + + return new AuthenticationResult + { + IsSuccessful = true, + Token = tokenHandler.WriteToken(token) + }; + } +} \ No newline at end of file