Upgrade packages and target NET 7.0
This commit is contained in:
parent
87d4a6373a
commit
e70bdee832
|
@ -96,11 +96,6 @@ namespace BlueWest.Data.Application.Users
|
|||
/// Gets or sets the number of failed login attempts for the current user.
|
||||
/// </summary>
|
||||
public override int AccessFailedCount { get; set; }
|
||||
|
||||
public List<SessionToken> SessionToken { get; set; }
|
||||
|
||||
public List<SessionData> SessionDatas { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -17,9 +17,8 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="6.0.8" />
|
||||
<PackageReference Include="Redis.OM" Version="0.2.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="7.0.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.10.0" />
|
||||
</ItemGroup>
|
||||
<Import Project="..\include\BlueWest.MapTo\src\BlueWest.MapTo\MapTo.props" />
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
using Redis.OM.Modeling;
|
||||
|
||||
namespace BlueWest.Data.Application
|
||||
{
|
||||
public class SessionCacheItem
|
||||
{
|
||||
public string UserId { get; set; }
|
||||
|
||||
[RedisIdField] [Indexed]
|
||||
public string SessionTokenId { get; set; }
|
||||
|
||||
[Indexed]
|
||||
public string AccessToken { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
using BlueWest.Data.Application.Users;
|
||||
|
||||
namespace BlueWest.Data.Application
|
||||
{
|
||||
public class SessionData
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string UserId { get; set; }
|
||||
public string SessionTokenId { get; set; }
|
||||
public SessionToken SessionToken { get; set; }
|
||||
public ApplicationUser User { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
using BlueWest.Data.Application.Users;
|
||||
using MapTo;
|
||||
using Redis.OM.Modeling;
|
||||
|
||||
namespace BlueWest.Data.Application
|
||||
{
|
||||
[Document(StorageType = StorageType.Json, Prefixes = new []{"SessionToken"})]
|
||||
[MapFrom(new []
|
||||
{
|
||||
typeof(SessionTokenUnique)
|
||||
})]
|
||||
public partial class SessionToken
|
||||
{
|
||||
[IgnoreMemberMapTo]
|
||||
[Indexed] public string Id { get; set; }
|
||||
|
||||
[Indexed] public long ValidFor { get; set;}
|
||||
|
||||
[Indexed] public bool IsValid { get; set; }
|
||||
|
||||
[Indexed] public long CreatedDate { get; set; }
|
||||
|
||||
[Indexed] public string UserId { get; set; }
|
||||
|
||||
[Indexed] public string AccessToken { get; set; }
|
||||
|
||||
|
||||
public bool Validate()
|
||||
{
|
||||
var expirationDate = CreatedDate + ValidFor;
|
||||
var timeNow = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
if (expirationDate < timeNow)
|
||||
{
|
||||
IsValid = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
using MapTo;
|
||||
|
||||
namespace BlueWest.Data.Application
|
||||
{
|
||||
[MapFrom(typeof(SessionToken))]
|
||||
public partial class SessionTokenUnique
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public long ValidFor { get; set;}
|
||||
public long CreatedDate { get; set; }
|
||||
public string UserId { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<LangVersion>10</LangVersion>
|
||||
<RootNamespace>BlueWest.WebApi</RootNamespace>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
|
@ -18,24 +18,22 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Grpc.AspNetCore" Version="2.49.0-pre1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authorization.Policy" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.8">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.2-mauipre.1.22102.15" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="6.0.2-mauipre.1.22054.8" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="7.0.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -2,12 +2,10 @@ namespace BlueWest.WebApi.Configuration
|
|||
{
|
||||
public class ConnectionStringDocker
|
||||
{
|
||||
public string Redis { get; set; }
|
||||
public string MySql { get; set; }
|
||||
}
|
||||
public class ConnectionStringNoDocker
|
||||
{
|
||||
public string Redis { get; set; }
|
||||
public string MySql { get; set; }
|
||||
}
|
||||
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
using System.Threading.Tasks;
|
||||
using BlueWest.Data.Application;
|
||||
using BlueWest.Data.Auth.Context.Users;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace BlueWest.Data.Auth
|
||||
{
|
||||
/// <summary>
|
||||
/// Methods for handling session cache data.
|
||||
/// </summary>
|
||||
public interface ISessionCache : IHostedService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a Session Token by Id.
|
||||
/// </summary>
|
||||
/// <param name="tokenId"></param>
|
||||
/// <returns></returns>
|
||||
Task<SessionToken> GetSessionTokenByIdAsync(string tokenId);
|
||||
/// <summary>
|
||||
/// Create a new session token
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
Task AddSessionToken(SessionToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Check for validity of the session
|
||||
/// </summary>
|
||||
/// <param name="sessionTokenId"></param>
|
||||
/// <returns></returns>
|
||||
Task<bool> IsSessionValidAsync(string sessionTokenId);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the session is valid
|
||||
/// </summary>
|
||||
/// <param name="sessionTokenId"></param>
|
||||
/// <returns></returns>
|
||||
bool IsSessionValid(string sessionTokenId);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Save Cache
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task SaveAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Save Cache
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
void Save();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using BlueWest.Data.Application;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace BlueWest.Data.Auth.Context.Users;
|
||||
|
||||
|
@ -9,9 +10,7 @@ public static class AuthConsts
|
|||
/// <summary>
|
||||
/// Helper object to return a negative callback
|
||||
/// </summary>
|
||||
public static (bool, SessionTokenUnique, ClaimsIdentity) NegativeToken => (false, null, null);
|
||||
|
||||
public static (bool, SessionTokenUnique, ClaimsIdentity) OkAuth(SessionTokenUnique sessionTokenUnique, ClaimsIdentity claimsIdentity, bool success = true) => (success, sessionTokenUnique, claimsIdentity);
|
||||
public static (ClaimsIdentity, bool) NegativeToken => (null, false);
|
||||
|
||||
|
||||
}
|
|
@ -1,10 +1,7 @@
|
|||
using System;
|
||||
using System.Security.Claims;
|
||||
using BlueWest.Cryptography;
|
||||
using BlueWest.Data.Application;
|
||||
using BlueWest.Data.Application.Users;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using static BlueWest.Data.Auth.Context.Users.AuthConsts;
|
||||
|
||||
|
@ -18,7 +15,6 @@ namespace BlueWest.Data.Auth.Context.Users
|
|||
private readonly ApplicationUserManager _userManager;
|
||||
private readonly IHasher _hasher;
|
||||
private readonly IJwtFactory _jwtFactory;
|
||||
private readonly ISessionCache _sessionCache;
|
||||
|
||||
/// <summary>
|
||||
/// Auth manager constructor
|
||||
|
@ -30,113 +26,22 @@ namespace BlueWest.Data.Auth.Context.Users
|
|||
public AuthManager(
|
||||
ApplicationUserManager userManager,
|
||||
IHasher hasher,
|
||||
IJwtFactory jwtFactory,
|
||||
ISessionCache sessionCache)
|
||||
IJwtFactory jwtFactory)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_hasher = hasher;
|
||||
_jwtFactory = jwtFactory;
|
||||
_sessionCache = sessionCache;
|
||||
}
|
||||
|
||||
private async Task<SessionToken> GetSessionToken(LoginRequest loginRequest)
|
||||
{
|
||||
var uuid = loginRequest.GetUuid();
|
||||
var hashUuid = GetHashFromUuid(uuid);
|
||||
var sessionToken = await _sessionCache.GetSessionTokenByIdAsync(hashUuid);
|
||||
return sessionToken;
|
||||
}
|
||||
|
||||
|
||||
private string GetHashFromUuid(string uuid)
|
||||
{
|
||||
return _hasher.CreateHash(uuid, BaseCryptoItem.HashAlgorithm.SHA2_512);
|
||||
}
|
||||
|
||||
private SessionToken GetNewSessionToken(LoginRequest loginRequest, ApplicationUser user)
|
||||
{
|
||||
long timeNow = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
|
||||
var newToken = new SessionToken
|
||||
{
|
||||
Id = GetHashFromUuid(loginRequest.GetUuid()),
|
||||
UserId = user.Id,
|
||||
CreatedDate = timeNow,
|
||||
IsValid = true,
|
||||
ValidFor = SessionConstants.DefaultSessionMaxAge.Milliseconds
|
||||
};
|
||||
|
||||
return newToken;
|
||||
}
|
||||
|
||||
public bool SessionTokenIsValid(SessionToken token)
|
||||
{
|
||||
var hasChanges = token.Validate();
|
||||
|
||||
if (hasChanges)
|
||||
{
|
||||
_sessionCache.SaveAsync();
|
||||
}
|
||||
|
||||
return token.IsValid;
|
||||
}
|
||||
|
||||
public async Task<(bool, SessionTokenUnique, ClaimsIdentity)> GetSessionTokenIdByLoginRequest(LoginRequest loginRequest, string authenticationType = JwtBearerDefaults.AuthenticationScheme)
|
||||
{
|
||||
var user = await _userManager.FindByEmailAsync(loginRequest.Email);
|
||||
|
||||
if (user == null) return NegativeToken;
|
||||
|
||||
if (!await _userManager.CheckPasswordAsync(user, loginRequest.Password)) return NegativeToken;
|
||||
|
||||
var identity = new ClaimsIdentity(authenticationType);
|
||||
identity.AddClaim(new Claim(ClaimTypes.Email, user.Email));
|
||||
identity.AddClaim(new Claim(ClaimTypes.MobilePhone, user.PhoneNumber));
|
||||
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
|
||||
|
||||
|
||||
var sessionToken = await GetSessionToken(loginRequest);
|
||||
|
||||
if (sessionToken == null || !SessionTokenIsValid(sessionToken))
|
||||
{
|
||||
var (success, bearerToken) = await GenerateBearerToken(identity, user);
|
||||
var newSessionToken = GetNewSessionToken(loginRequest, user);
|
||||
await _sessionCache.AddSessionToken(newSessionToken);
|
||||
var tokenUnique = new SessionTokenUnique(newSessionToken);
|
||||
return OkAuth(tokenUnique, identity, success);
|
||||
}
|
||||
|
||||
var response = new SessionTokenUnique(sessionToken);
|
||||
return OkAuth(response, identity);
|
||||
}
|
||||
|
||||
public async Task<(bool, SessionTokenUnique, ClaimsIdentity)> GetSessionTokenIdByLoginRequestViaCookie(LoginRequest loginRequest, string authenticationType = CookieAuthenticationDefaults.AuthenticationScheme)
|
||||
{
|
||||
var user = await _userManager.FindByEmailAsync(loginRequest.Email);
|
||||
|
||||
if (user == null) return NegativeToken;
|
||||
|
||||
if (!await _userManager.CheckPasswordAsync(user, loginRequest.Password)) return NegativeToken;
|
||||
|
||||
var identity = new ClaimsIdentity(authenticationType);
|
||||
identity.AddClaim(new Claim(ClaimTypes.Email, user.Email));
|
||||
identity.AddClaim(new Claim(ClaimTypes.MobilePhone, user.PhoneNumber));
|
||||
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
|
||||
|
||||
|
||||
var sessionToken = await GetSessionToken(loginRequest);
|
||||
|
||||
if (sessionToken == null || !SessionTokenIsValid(sessionToken))
|
||||
{
|
||||
var newSessionToken = GetNewSessionToken(loginRequest, user);
|
||||
await _sessionCache.AddSessionToken(newSessionToken);
|
||||
var tokenUnique = new SessionTokenUnique(newSessionToken);
|
||||
return OkAuth(tokenUnique, identity);
|
||||
}
|
||||
|
||||
var response = new SessionTokenUnique(sessionToken);
|
||||
return OkAuth(response, identity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async Task<(bool, string)> GenerateBearerToken(ClaimsIdentity identity, ApplicationUser user)
|
||||
{
|
||||
|
@ -171,5 +76,22 @@ namespace BlueWest.Data.Auth.Context.Users
|
|||
var newUser = userSignupDto.ToUser();
|
||||
return await _userManager.CreateAsync(newUser);
|
||||
}
|
||||
|
||||
public async Task<(ClaimsIdentity, bool)> DoLogin(LoginRequest loginRequest)
|
||||
{
|
||||
var user = await _userManager.FindByEmailAsync(loginRequest.Email);
|
||||
|
||||
if (user == null) return NegativeToken;
|
||||
|
||||
if (!await _userManager.CheckPasswordAsync(user, loginRequest.Password)) return NegativeToken;
|
||||
|
||||
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
identity.AddClaim(new Claim(ClaimTypes.Email, user.Email));
|
||||
identity.AddClaim(new Claim(ClaimTypes.MobilePhone, user.PhoneNumber));
|
||||
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
|
||||
|
||||
|
||||
return (identity, true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,23 +17,11 @@ public interface IAuthManager
|
|||
/// <param name="registerRequest"></param>
|
||||
/// <returns></returns>
|
||||
Task<IdentityResult> CreateUserAsync(RegisterRequest registerRequest);
|
||||
|
||||
/// <summary>
|
||||
/// Does Login
|
||||
/// </summary>
|
||||
/// <param name="loginRequest"></param>
|
||||
/// <returns></returns>
|
||||
public Task<(bool, SessionTokenUnique, ClaimsIdentity)> GetSessionTokenIdByLoginRequest(LoginRequest loginRequest, string authenticationType);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Does Login
|
||||
/// </summary>
|
||||
/// <param name="loginRequest"></param>
|
||||
/// <returns></returns>
|
||||
public Task<(bool, SessionTokenUnique, ClaimsIdentity)> GetSessionTokenIdByLoginRequestViaCookie(LoginRequest loginRequest, string authenticationType);
|
||||
|
||||
|
||||
|
||||
Task<(ClaimsIdentity, bool)> DoLogin(LoginRequest loginRequest);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -17,8 +17,8 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<LangVersion>10</LangVersion>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
|
@ -10,24 +10,23 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Grpc.AspNetCore" Version="2.50.0-pre1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authorization.Policy" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.8">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.2-mauipre.1.22102.15" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="6.0.2-mauipre.1.22054.8" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="7.0.0" />
|
||||
<PackageReference Include="Npgsql" Version="7.0.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -86,26 +86,7 @@ namespace CodeLiturgy.Domain.Model
|
|||
|
||||
builder.Entity<ApplicationRoleClaim>().ToTable("RoleClaims");
|
||||
builder.Entity<ApplicationUserRole>().ToTable("UserRole");
|
||||
|
||||
|
||||
// Session Token Primary Key
|
||||
builder.Entity<SessionToken>(b =>
|
||||
b.HasKey(x => x.Id));
|
||||
builder.Entity<SessionToken>(b =>
|
||||
b.Property(x => x.Id).ValueGeneratedOnAdd());
|
||||
|
||||
// Session Data
|
||||
builder.Entity<SessionData>()
|
||||
.HasOne(b => b.User)
|
||||
.WithMany(x => x.SessionDatas)
|
||||
.HasForeignKey(x => x.UserId);
|
||||
|
||||
|
||||
// Session Data Primary Key
|
||||
builder.Entity<SessionData>(b =>
|
||||
b.HasKey(x => x.Id));
|
||||
builder.Entity<SessionData>(b =>
|
||||
b.Property(x => x.Id).ValueGeneratedOnAdd());
|
||||
|
||||
|
||||
//.ConfigureIdentityModel();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
|
@ -9,8 +9,8 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.8">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
|
|
@ -28,12 +28,11 @@ namespace CodeLiturgy.Views.Controllers
|
|||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[Microsoft.AspNetCore.Mvc.ActionName("LoginAction")]
|
||||
[ActionName("LoginAction")]
|
||||
public async Task<IActionResult> LoginAction(LoginRequest loginRequest)
|
||||
{
|
||||
var (success, sessionToken, identity) =
|
||||
await _authManager.GetSessionTokenIdByLoginRequestViaCookie(loginRequest,
|
||||
CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
var (identity,success) =
|
||||
await _authManager.DoLogin(loginRequest);
|
||||
|
||||
|
||||
if (!success) return Redirect(AuthLoginRoute);
|
||||
|
|
|
@ -1,131 +0,0 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BlueWest.Data.Application;
|
||||
using BlueWest.Data.Auth;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Redis.OM;
|
||||
using Redis.OM.Searching;
|
||||
|
||||
namespace CodeLiturgy.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Session Provider Context
|
||||
/// </summary>
|
||||
public sealed class SessionManager : ISessionCache
|
||||
{
|
||||
private readonly RedisConnectionProvider _provider;
|
||||
private readonly RedisCollection<SessionToken> _sessionTokens;
|
||||
|
||||
/// <summary>
|
||||
/// Index Creation Device
|
||||
/// </summary>
|
||||
/// <param name="provider">Redis connection</param>
|
||||
public SessionManager(
|
||||
RedisConnectionProvider provider)
|
||||
{
|
||||
_provider = provider;
|
||||
_sessionTokens = (RedisCollection<SessionToken>) provider.RedisCollection<SessionToken>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Empty constructor
|
||||
/// </summary>
|
||||
public SessionManager()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a session token by the respective Id.
|
||||
/// </summary>
|
||||
/// <param name="tokenId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<SessionToken> GetSessionTokenByIdAsync(string tokenId)
|
||||
{
|
||||
return
|
||||
await _sessionTokens.Where(x => x.Id == tokenId)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new session token
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
public async Task AddSessionToken(SessionToken token)
|
||||
{
|
||||
await _sessionTokens.InsertAsync(token);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SaveAsync()
|
||||
{
|
||||
await _sessionTokens.SaveAsync();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Save session data
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
_sessionTokens.Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a Bearer By Access Token Id
|
||||
/// </summary>
|
||||
/// <param name="sessionTokenId"></param>
|
||||
public async Task<bool> IsSessionValidAsync(string sessionTokenId)
|
||||
{
|
||||
var accessToken = await _sessionTokens
|
||||
.Where(t => t.Id == sessionTokenId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (accessToken == null) return false;
|
||||
|
||||
if (accessToken.IsValid)
|
||||
{
|
||||
// Check if it's not expired
|
||||
var expirationDate = accessToken.CreatedDate + accessToken.ValidFor;
|
||||
var timeNow = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
if (expirationDate >= timeNow) return accessToken.IsValid;
|
||||
accessToken.IsValid = false;
|
||||
await _sessionTokens.SaveAsync();
|
||||
}
|
||||
|
||||
return accessToken.IsValid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a session is valid
|
||||
/// </summary>
|
||||
/// <param name="sessionTokenId"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsSessionValid(string sessionTokenId)
|
||||
{
|
||||
var accessToken = _sessionTokens
|
||||
.FirstOrDefault(t => t.Id == sessionTokenId);
|
||||
|
||||
if (accessToken == null) return false;
|
||||
|
||||
if (!accessToken.IsValid) return accessToken.IsValid;
|
||||
|
||||
accessToken.Validate();
|
||||
_sessionTokens.Save();
|
||||
|
||||
return accessToken.IsValid;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _provider.Connection.CreateIndexAsync(typeof(SessionToken));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
|
@ -46,7 +46,7 @@ public class Startup
|
|||
|
||||
|
||||
services.AddAuthServerServices(_configuration, _environment);
|
||||
services.PrepareMySqlDatabasePool(_configuration, _environment);
|
||||
services.PreparePostgresqlDatabasePool(_configuration, _environment);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -11,14 +11,15 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Redis.OM;
|
||||
|
||||
namespace CodeLiturgy.Views;
|
||||
|
||||
public static class StartupExtensions
|
||||
{
|
||||
/*
|
||||
private static MySqlServerVersion GetMySqlServerVersion(int major, int minor, int build) =>
|
||||
new(new Version(major, minor, build));
|
||||
*/
|
||||
|
||||
private static string GetConnectionString(this IConfiguration configurationRoot, string db)
|
||||
{
|
||||
|
@ -45,14 +46,6 @@ public static class StartupExtensions
|
|||
internal static IServiceCollection AddAuthServerServices(this IServiceCollection services,
|
||||
IConfiguration configuration, IWebHostEnvironment environment)
|
||||
{
|
||||
var connectionString = configuration.GetConnectionString("Redis");
|
||||
|
||||
if (string.IsNullOrEmpty(connectionString))
|
||||
{
|
||||
throw new InvalidOperationException("Redis connection string is empty");
|
||||
}
|
||||
|
||||
|
||||
services.AddSession(options =>
|
||||
{
|
||||
options.Cookie.Domain = SessionConstants.CookieDomain;
|
||||
|
@ -61,11 +54,8 @@ public static class StartupExtensions
|
|||
});
|
||||
|
||||
services
|
||||
.AddSingleton(new RedisConnectionProvider(connectionString))
|
||||
.AddScoped<IJwtTokenHandler, JwtTokenHandler>()
|
||||
.AddScoped<IJwtFactory, JwtFactory>()
|
||||
.AddHostedService<SessionManager>()
|
||||
.AddSingleton<ISessionCache, SessionManager>()
|
||||
.AddScoped<UserRepository>()
|
||||
.AddScoped<IUserManager, ApplicationUserManager>()
|
||||
.AddScoped<IAuthManager, AuthManager>()
|
||||
|
@ -164,6 +154,7 @@ public static class StartupExtensions
|
|||
/// <param name="optionsBuilder"></param>
|
||||
/// <param name="configuration"></param>
|
||||
/// <param name="environment"></param>
|
||||
/*
|
||||
private static DbContextOptionsBuilder GetMySqlSettings(
|
||||
this DbContextOptionsBuilder optionsBuilder,
|
||||
IConfiguration configuration,
|
||||
|
@ -200,7 +191,9 @@ public static class StartupExtensions
|
|||
|
||||
return optionsBuilder;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Setup database Contexts
|
||||
/// </summary>
|
||||
|
@ -208,15 +201,17 @@ public static class StartupExtensions
|
|||
/// <param name="configuration"></param>
|
||||
/// <param name="environment"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection PrepareMySqlDatabasePool(this IServiceCollection serviceCollection,
|
||||
public static IServiceCollection PreparePostgresqlDatabasePool(this IServiceCollection serviceCollection,
|
||||
IConfiguration configuration, IWebHostEnvironment environment)
|
||||
{
|
||||
return serviceCollection
|
||||
.AddDbContextPool<UserDbContext>(options =>
|
||||
options.GetMySqlSettings(configuration, environment))
|
||||
.AddDbContextPool<CountryDbContext>(options =>
|
||||
options.GetMySqlSettings(configuration, environment))
|
||||
.AddDbContextPool<ApplicationUserDbContext>(options =>
|
||||
options.GetMySqlSettings(configuration, environment));
|
||||
return serviceCollection;
|
||||
/*.AddDbContextPool<UserDbContext>(options =>
|
||||
options.GetMySqlSettings(configuration, environment))
|
||||
.AddDbContextPool<CountryDbContext>(options =>
|
||||
options.GetMySqlSettings(configuration, environment))
|
||||
.AddDbContextPool<ApplicationUserDbContext>(options =>
|
||||
options.GetMySqlSettings(configuration, environment));*/
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"sdk": {
|
||||
"version": "7.0.0",
|
||||
"rollForward": "latestMajor",
|
||||
"allowPrerelease": true
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue