127 lines
4.8 KiB
C#

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Text;
using System.Security.Cryptography;
using Manager.Interfaces.Models;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using Manager.Services;
using ManagerService.Helpers;
using ManagerService.DTOs;
using ManagerService.Data;
namespace ManagerService.Service.Services
{
/// <summary>
/// Tokens service
/// </summary>
public class TokensService
{
private readonly ILogger<TokensService> _logger;
private readonly TokensSettings _tokenSettings;
private readonly ProfileLogic _profileLogic;
/*private InstanceDatabaseService _instanceService;*/
private readonly MyInfoMateDbContext _myInfoMateDbContext;
private readonly SigningCredentials _signingCredentials;
/// <summary>
/// Constructor
/// </summary>
/// <param name="logger">Logger</param>
/// <param name="tokenSettings">Tokens settings</param>
/// <param name="context">Database context</param>
/// <param name="profileLogic">Profile logic</param>
/// <param name="emailClient">Email client</param>
public TokensService(ILogger<TokensService> logger, IOptions<TokensSettings> tokenSettings, ProfileLogic profileLogic, MyInfoMateDbContext myInfoMateDbContext)
{
_logger = logger;
_tokenSettings = tokenSettings.Value;
_profileLogic = profileLogic;
_myInfoMateDbContext = myInfoMateDbContext;
var key = Encoding.UTF8.GetBytes(_tokenSettings.Secret);
_signingCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature);
}
/// <summary>
/// Authenticate
/// </summary>
/// <param name="email">Email</param>
/// <param name="password">Password</param>
/// <returns>Token DTO in case of success</returns>
public TokenDTO Authenticate(User user, string password)
{
try
{
var expiration = DateTime.UtcNow.AddMinutes(_tokenSettings.AccessTokenExpiration);
_profileLogic.TestPassword(user.Email, user.Password, password);
var claims = new List<System.Security.Claims.Claim>
{
new(ClaimTypes.Email, user.Email),
new(ClaimTypes.Name, $"{user.FirstName} {user.LastName}"),
new(Security.ClaimTypes.InstanceId, user.InstanceId),
};
foreach (var perm in Security.RolePermissions[user.Role])
claims.Add(new Claim(Security.ClaimTypes.Permission, perm));
var tokenHandler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor()
{
Subject = new ClaimsIdentity(claims),
Expires = expiration,
SigningCredentials = _signingCredentials
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var instance = _myInfoMateDbContext.Instances.Find(user.InstanceId);
return new TokenDTO()
{
access_token = tokenHandler.WriteToken(token),
expires_in = _tokenSettings.AccessTokenExpiration * 60,
expiration = new DateTimeOffset(token.ValidTo),
token_type = "Bearer",
scope = Security.Scope,
instanceId = user.InstanceId,
pinCode = instance.PinCode,
role = user.Role
};
}
catch (UnauthorizedAccessException ex)
{
_logger?.LogError(ex, $"Authenticate error for user '{user.Email}': unauthorized access");
throw;
}
catch (Exception ex)
{
_logger?.LogError(ex, $"Authenticate error for user '{user.Email}': {ex.Message}");
throw;
}
}
public static string GenerateSHA256String(string inputString)
{
SHA256 sha256 = SHA256Managed.Create();
byte[] bytes = Encoding.UTF8.GetBytes(inputString);
byte[] hash = sha256.ComputeHash(bytes);
return GetStringFromHash(hash);
}
public static string GetStringFromHash(byte[] hash)
{
StringBuilder result = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
result.Append(hash[i].ToString("X2"));
}
return result.ToString();
}
}
}