141 lines
5.1 KiB
C#
141 lines
5.1 KiB
C#
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Security.Claims;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Security.Cryptography;
|
|
using Manager.Interfaces.Models;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
using Manager.Framework.Business;
|
|
using Manager.Interfaces.DTO;
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
|
|
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 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)
|
|
{
|
|
_logger = logger;
|
|
_tokenSettings = tokenSettings.Value;
|
|
_profileLogic = profileLogic;
|
|
|
|
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 claims = new List<System.Security.Claims.Claim>();
|
|
var expiration = DateTime.UtcNow.AddMinutes(_tokenSettings.AccessTokenExpiration);
|
|
|
|
_profileLogic.TestPassword(user.Email, user.Password, password);
|
|
|
|
claims.Add(new Claim(ClaimTypes.Email, user.Email));
|
|
|
|
// TODO: add refresh token support
|
|
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
var tokenDescriptor = new SecurityTokenDescriptor()
|
|
{
|
|
Subject = new ClaimsIdentity(claims),
|
|
Expires = expiration,
|
|
SigningCredentials = _signingCredentials
|
|
};
|
|
var token = tokenHandler.CreateToken(tokenDescriptor);
|
|
|
|
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
|
|
};
|
|
}
|
|
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 object GenerateToken(string username)
|
|
{
|
|
var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("WVD[&vAwis9=#883bM$FRc0Mw8h")); // Put the secret in a file or something
|
|
|
|
var claims = new Claim[] {
|
|
new Claim(ClaimTypes.Name, username),
|
|
new Claim(JwtRegisteredClaimNames.Email, "john.doe@blinkingcaret.com"),
|
|
new Claim(ClaimTypes.Role, "Admin")
|
|
};
|
|
|
|
var token = new JwtSecurityToken(
|
|
issuer: "Manager App",
|
|
audience: "Manager client",
|
|
claims: claims,
|
|
notBefore: DateTime.Now,
|
|
expires: DateTime.Now.AddDays(28),
|
|
signingCredentials: new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256)
|
|
);
|
|
|
|
string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
|
|
|
|
return jwtToken;
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|