Services, service registration and dependency injection for auth
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
using AipsCore.Domain.Models.User;
|
||||||
|
|
||||||
|
namespace AipsCore.Application.Abstract.UserContext;
|
||||||
|
|
||||||
|
public interface ITokenProvider
|
||||||
|
{
|
||||||
|
string Generate(User user, IList<string> roles);
|
||||||
|
}
|
||||||
3
dotnet/AipsCore/Application/Authentication/Token.cs
Normal file
3
dotnet/AipsCore/Application/Authentication/Token.cs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AipsCore.Application.Authentication;
|
||||||
|
|
||||||
|
public record Token(string Value);
|
||||||
@@ -14,7 +14,7 @@ public static class AipsRegistrationExtensions
|
|||||||
|
|
||||||
services.AddPersistence(configuration);
|
services.AddPersistence(configuration);
|
||||||
|
|
||||||
services.AddUserContext();
|
services.AddUserContext(configuration);
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,67 @@
|
|||||||
|
using System.Text;
|
||||||
using AipsCore.Application.Abstract.UserContext;
|
using AipsCore.Application.Abstract.UserContext;
|
||||||
|
using AipsCore.Infrastructure.Persistence.Authentication;
|
||||||
|
using AipsCore.Infrastructure.Persistence.Db;
|
||||||
|
using AipsCore.Infrastructure.Persistence.User;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
namespace AipsCore.Infrastructure.DI;
|
namespace AipsCore.Infrastructure.DI;
|
||||||
|
|
||||||
public static class UserContextRegistrationExtension
|
public static class UserContextRegistrationExtension
|
||||||
{
|
{
|
||||||
public static IServiceCollection AddUserContext(this IServiceCollection services)
|
public static IServiceCollection AddUserContext(this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
services.AddTransient<IUserContext, UserContext>();
|
var jwtSettings = new JwtSettings
|
||||||
|
{
|
||||||
|
Issuer = configuration["JWT_ISSUER"]!,
|
||||||
|
Audience = configuration["JWT_AUDIENCE"]!,
|
||||||
|
Key = configuration["JWT_KEY"]!,
|
||||||
|
ExpirationMinutes = int.Parse(configuration["JWT_EXPIRATION_MINUTES"] ?? "60")
|
||||||
|
};
|
||||||
|
|
||||||
|
services.AddSingleton(jwtSettings);
|
||||||
|
|
||||||
|
services.AddHttpContextAccessor();
|
||||||
|
|
||||||
|
services.AddIdentityCore<User>(options =>
|
||||||
|
{
|
||||||
|
options.Password.RequiredLength = 8;
|
||||||
|
options.Password.RequireDigit = true;
|
||||||
|
options.Password.RequireLowercase = true;
|
||||||
|
options.Password.RequireUppercase = true;
|
||||||
|
options.Password.RequireNonAlphanumeric = true;
|
||||||
|
|
||||||
|
options.User.RequireUniqueEmail = true;
|
||||||
|
})
|
||||||
|
.AddRoles<IdentityRole<Guid>>()
|
||||||
|
.AddEntityFrameworkStores<AipsDbContext>()
|
||||||
|
.AddSignInManager()
|
||||||
|
.AddDefaultTokenProviders();
|
||||||
|
|
||||||
|
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
.AddJwtBearer(options =>
|
||||||
|
{
|
||||||
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuer = true,
|
||||||
|
ValidateAudience = true,
|
||||||
|
ValidateLifetime = true,
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
ValidIssuer = jwtSettings.Issuer,
|
||||||
|
ValidAudience = jwtSettings.Audience,
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(
|
||||||
|
Encoding.UTF8.GetBytes(jwtSettings.Key))
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddAuthorization();
|
||||||
|
|
||||||
|
services.AddTransient<IUserContext, HttpUserContext>();
|
||||||
|
services.AddTransient<ITokenProvider, JwtTokenProvider>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using System.Security.Claims;
|
||||||
|
using AipsCore.Application.Abstract.UserContext;
|
||||||
|
using AipsCore.Domain.Models.User.ValueObjects;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
|
namespace AipsCore.Infrastructure.Persistence.Authentication;
|
||||||
|
|
||||||
|
public class HttpUserContext : IUserContext
|
||||||
|
{
|
||||||
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
|
|
||||||
|
public HttpUserContext(IHttpContextAccessor httpContextAccessor)
|
||||||
|
{
|
||||||
|
_httpContextAccessor = httpContextAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserId GetCurrentUserId()
|
||||||
|
{
|
||||||
|
var user = _httpContextAccessor.HttpContext?.User;
|
||||||
|
|
||||||
|
if (user is null || !user.Identity!.IsAuthenticated)
|
||||||
|
{
|
||||||
|
throw new UnauthorizedAccessException("User is not authenticated");
|
||||||
|
}
|
||||||
|
|
||||||
|
var userIdClaim = user.FindFirst(ClaimTypes.NameIdentifier);
|
||||||
|
|
||||||
|
if (userIdClaim is null)
|
||||||
|
{
|
||||||
|
throw new UnauthorizedAccessException("User id claim not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new UserId(userIdClaim.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace AipsCore.Infrastructure.Persistence.Authentication;
|
||||||
|
|
||||||
|
public sealed class JwtSettings
|
||||||
|
{
|
||||||
|
public string Issuer { get; init; } = null!;
|
||||||
|
public string Audience { get; init; } = null!;
|
||||||
|
public string Key { get; init; } = null!;
|
||||||
|
public int ExpirationMinutes { get; init; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
|
using AipsCore.Application.Abstract.UserContext;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
namespace AipsCore.Infrastructure.Persistence.Authentication;
|
||||||
|
|
||||||
|
public class JwtTokenProvider : ITokenProvider
|
||||||
|
{
|
||||||
|
private readonly JwtSettings _jwtSettings;
|
||||||
|
|
||||||
|
public JwtTokenProvider(JwtSettings jwtSettings)
|
||||||
|
{
|
||||||
|
_jwtSettings = jwtSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Generate(Domain.Models.User.User user, IList<string> roles)
|
||||||
|
{
|
||||||
|
var claims = new List<Claim>
|
||||||
|
{
|
||||||
|
new Claim(ClaimTypes.NameIdentifier, user.Id.IdValue),
|
||||||
|
new Claim(ClaimTypes.Email, user.Email.EmailValue)
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var role in roles)
|
||||||
|
{
|
||||||
|
claims.Add(new Claim(ClaimTypes.Role, role));
|
||||||
|
}
|
||||||
|
|
||||||
|
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.Key));
|
||||||
|
|
||||||
|
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
||||||
|
|
||||||
|
var token = new JwtSecurityToken(
|
||||||
|
issuer: _jwtSettings.Issuer,
|
||||||
|
audience: _jwtSettings.Audience,
|
||||||
|
claims: claims,
|
||||||
|
expires: DateTime.UtcNow.AddMinutes(_jwtSettings.ExpirationMinutes),
|
||||||
|
signingCredentials: credentials);
|
||||||
|
|
||||||
|
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace AipsCore.Infrastructure.Persistence.Db;
|
namespace AipsCore.Infrastructure.Persistence.Db;
|
||||||
|
|
||||||
public class AipsDbContext : DbContext
|
public class AipsDbContext : IdentityDbContext<User.User, IdentityRole<Guid>, Guid>
|
||||||
{
|
{
|
||||||
public DbSet<User.User> Users { get; set; }
|
|
||||||
public DbSet<Whiteboard.Whiteboard> Whiteboards { get; set; }
|
public DbSet<Whiteboard.Whiteboard> Whiteboards { get; set; }
|
||||||
public DbSet<Shape.Shape> Shapes { get; set; }
|
public DbSet<Shape.Shape> Shapes { get; set; }
|
||||||
public DbSet<WhiteboardMembership.WhiteboardMembership> WhiteboardMemberships { get; set; }
|
public DbSet<WhiteboardMembership.WhiteboardMembership> WhiteboardMemberships { get; set; }
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
using AipsCore.Application.Abstract.UserContext;
|
|
||||||
using AipsCore.Domain.Models.User.ValueObjects;
|
|
||||||
|
|
||||||
namespace AipsCore.Infrastructure;
|
|
||||||
|
|
||||||
public class UserContext : IUserContext
|
|
||||||
{
|
|
||||||
public UserId GetCurrentUserId()
|
|
||||||
{
|
|
||||||
return new UserId(new Guid("52a1810c-802f-48b0-a74c-7b517807e392").ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Ovo je samo trenutno resenje
|
|
||||||
Reference in New Issue
Block a user