authorization system
parent
0e9d048a74
commit
3d635dab60
|
@ -3,11 +3,8 @@ using Microsoft.Extensions.Logging;
|
|||
using Microsoft.Extensions.Options;
|
||||
using NetworkResurrector.Application.Services;
|
||||
using NetworkResurrector.Domain.Entities;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -31,12 +28,9 @@ namespace NetworkResurrector.Api.Authentication
|
|||
User user;
|
||||
try
|
||||
{
|
||||
var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
|
||||
var credentialBytes = Convert.FromBase64String(authHeader.Parameter);
|
||||
var credentials = Encoding.UTF8.GetString(credentialBytes).Split(':');
|
||||
var username = credentials.First();
|
||||
var password = credentials.Last();
|
||||
user = await _userService.Authenticate(username, password);
|
||||
var authorizationHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
|
||||
var token = authorizationHeader.Parameter;
|
||||
user = await _userService.Authenticate(token);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -47,7 +41,7 @@ namespace NetworkResurrector.Api.Authentication
|
|||
return AuthenticateResult.Fail("Invalid Username or Password");
|
||||
|
||||
var claims = new[] {
|
||||
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
||||
new Claim(ClaimTypes.NameIdentifier, user.UserId.ToString()),
|
||||
new Claim(ClaimTypes.Name, user.UserName),
|
||||
};
|
||||
|
||||
|
|
|
@ -18,11 +18,18 @@ namespace NetworkResurrector.Api.Controllers
|
|||
_mediator = mediator;
|
||||
}
|
||||
|
||||
[HttpGet("token")]
|
||||
[AllowAnonymous]
|
||||
[HttpGet("token/{userName}/{password}")]
|
||||
public async Task<IActionResult> GetToken([FromRoute] GetToken.Query query)
|
||||
{
|
||||
var result = await _mediator.Send(query);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet("validate-token")]
|
||||
public IActionResult ValidateToken()
|
||||
{
|
||||
return Ok("Valid");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,11 @@
|
|||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Credentials": {
|
||||
"Users": [
|
||||
{
|
||||
"UserId": 1,
|
||||
"UserName": "***REMOVED***",
|
||||
"Password": "***REMOVED***"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NetworkResurrector.Application.Services;
|
||||
using NetworkResurrector.Application.Stores;
|
||||
using NetworkResurrector.Domain.Services;
|
||||
|
||||
namespace NetworkResurrector.Application
|
||||
|
@ -10,6 +11,12 @@ namespace NetworkResurrector.Application
|
|||
{
|
||||
services.AddSingleton<IParamProvider, ParamProvider>();
|
||||
services.AddScoped<IUserService, UserService>();
|
||||
services.AddStores();
|
||||
}
|
||||
|
||||
private static void AddStores(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<ISecurityStore, SecurityStore>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using AutoMapper;
|
||||
using NetworkResurrector.Application.Queries;
|
||||
using NetworkResurrector.Domain.Models;
|
||||
|
||||
namespace NetworkResurrector.Application.Mappings
|
||||
{
|
||||
|
@ -6,6 +8,7 @@ namespace NetworkResurrector.Application.Mappings
|
|||
{
|
||||
public MappingProfile()
|
||||
{
|
||||
CreateMap<SecurityToken, GetToken.Model>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using AutoMapper;
|
||||
using MediatR;
|
||||
using NetworkResurrector.Application.Services;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -17,23 +18,29 @@ namespace NetworkResurrector.Application.Queries
|
|||
|
||||
public class Model
|
||||
{
|
||||
public Guid Token { get; set; }
|
||||
public string Token { get; set; }
|
||||
public DateTime ValidUntil { get; set; }
|
||||
}
|
||||
|
||||
public class QueryHandler : IRequestHandler<Query, Model>
|
||||
{
|
||||
private readonly IUserService _userService;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public QueryHandler(IMapper mapper)
|
||||
public QueryHandler(IUserService userService, IMapper mapper)
|
||||
{
|
||||
_userService = userService;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<Model> Handle(Query request, CancellationToken cancellationToken)
|
||||
{
|
||||
var securityToken = await _userService.Login(request.UserName, request.Password);
|
||||
if (securityToken == null)
|
||||
return null;
|
||||
|
||||
return new Model() { Token = Guid.NewGuid(), ValidUntil = DateTime.Now };
|
||||
var result = _mapper.Map<Model>(securityToken);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using NetworkResurrector.Domain.Models.Settings;
|
||||
using NetworkResurrector.Domain.Entities;
|
||||
using NetworkResurrector.Domain.Services;
|
||||
|
||||
namespace NetworkResurrector.Application.Services
|
||||
|
@ -13,6 +13,6 @@ namespace NetworkResurrector.Application.Services
|
|||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public Credentials Credentials => _configuration.GetSection("Credentials").Get<Credentials>();
|
||||
public User[] Users => _configuration.GetSection("Users").Get<User[]>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,53 @@
|
|||
using NetworkResurrector.Domain.Entities;
|
||||
using NetworkResurrector.Application.Stores;
|
||||
using NetworkResurrector.Domain.Entities;
|
||||
using NetworkResurrector.Domain.Models;
|
||||
using NetworkResurrector.Domain.Services;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NetworkResurrector.Application.Services
|
||||
{
|
||||
public interface IUserService
|
||||
{
|
||||
Task<User> Authenticate(string username, string password);
|
||||
Task<SecurityToken> Login(string userName, string password);
|
||||
Task<User> Authenticate(string token);
|
||||
}
|
||||
|
||||
public class UserService : IUserService
|
||||
{
|
||||
private readonly IParamProvider _paramProvider;
|
||||
private readonly ISecurityStore _securityStore;
|
||||
|
||||
public UserService(IParamProvider paramProvider)
|
||||
public UserService(IParamProvider paramProvider, ISecurityStore securityStore)
|
||||
{
|
||||
_paramProvider = paramProvider;
|
||||
_securityStore = securityStore;
|
||||
}
|
||||
|
||||
public async Task<User> Authenticate(string username, string password)
|
||||
public async Task<SecurityToken> Login(string userName, string password)
|
||||
{
|
||||
return await Task.Run(() => CheckCredentials(username, password));
|
||||
var user = _paramProvider.Users.FirstOrDefault(z => z.UserName == userName && z.Password == password);
|
||||
if (user == null)
|
||||
return null;
|
||||
|
||||
var token = $"{Guid.NewGuid()}-{Guid.NewGuid()}-{user.UserId}";
|
||||
_securityStore.SetToken(token, user.UserId);
|
||||
|
||||
var securityToken = new SecurityToken() { UserId = user.UserId, Token = token };
|
||||
return securityToken;
|
||||
}
|
||||
|
||||
private User CheckCredentials(string username, string password)
|
||||
public async Task<User> Authenticate(string token)
|
||||
{
|
||||
if (_paramProvider.Credentials.UserName == username && _paramProvider.Credentials.Password == password)
|
||||
return new User() { UserName = username, Id = 1 };
|
||||
else
|
||||
var tokenValidation = _securityStore.ValidateToken(token);
|
||||
if (tokenValidation.Success)
|
||||
{
|
||||
var user = _paramProvider.Users.FirstOrDefault(z => z.UserId == tokenValidation.UserId);
|
||||
if (user != null)
|
||||
return user;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
using NetworkResurrector.Domain.Models;
|
||||
|
||||
namespace NetworkResurrector.Application.Stores
|
||||
{
|
||||
public interface ISecurityStore
|
||||
{
|
||||
void SetToken(string token, int userId);
|
||||
TokenValidation ValidateToken(string token);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
using NetworkResurrector.Domain.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace NetworkResurrector.Application.Stores
|
||||
{
|
||||
public class SecurityStore : ISecurityStore
|
||||
{
|
||||
private List<SecurityToken> Tokens { get; }
|
||||
|
||||
public SecurityStore()
|
||||
{
|
||||
Tokens = new List<SecurityToken>();
|
||||
}
|
||||
|
||||
public void SetToken(string token, int userId)
|
||||
{
|
||||
var registered = Tokens.FirstOrDefault(z => z.UserId == userId);
|
||||
if (registered == null)
|
||||
Tokens.Add(new SecurityToken() { UserId = userId, Token = token });
|
||||
else
|
||||
registered.Token = token;
|
||||
}
|
||||
|
||||
public TokenValidation ValidateToken(string token)
|
||||
{
|
||||
var lastIndexOfSeparator = token.LastIndexOf('-') + 1;
|
||||
var userIdString = token.Substring(lastIndexOfSeparator, token.Length - lastIndexOfSeparator);
|
||||
|
||||
if (!int.TryParse(userIdString, out int userId))
|
||||
return InvalidToken;
|
||||
|
||||
var valid = Tokens.FirstOrDefault(z => z.UserId == userId && z.Token == token);
|
||||
if (valid != null)
|
||||
return new TokenValidation() { Success = true, UserId = userId };
|
||||
|
||||
return InvalidToken;
|
||||
}
|
||||
|
||||
private TokenValidation InvalidToken => new TokenValidation() { Success = false };
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
public class User
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int UserId { get; set; }
|
||||
public string UserName { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
|
||||
namespace NetworkResurrector.Domain.Models
|
||||
{
|
||||
public class SecurityToken
|
||||
{
|
||||
public int UserId { get; set; }
|
||||
public string Token { get; set; }
|
||||
public DateTime ValidUntil { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
namespace NetworkResurrector.Domain.Models
|
||||
{
|
||||
public class TokenValidation
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public int UserId { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
using NetworkResurrector.Domain.Models.Settings;
|
||||
using NetworkResurrector.Domain.Entities;
|
||||
|
||||
namespace NetworkResurrector.Domain.Services
|
||||
{
|
||||
public interface IParamProvider
|
||||
{
|
||||
Credentials Credentials { get; }
|
||||
User[] Users { get; }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue