diff --git a/Directory.Packages.props b/Directory.Packages.props
index 625136bc..168d0cff 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -5,30 +5,33 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
+
-
+
+
+
+
\ No newline at end of file
diff --git a/Marechai.Server/Marechai.Server.csproj b/Marechai.Server/Marechai.Server.csproj
index fb298ef3..d4ee83db 100644
--- a/Marechai.Server/Marechai.Server.csproj
+++ b/Marechai.Server/Marechai.Server.csproj
@@ -9,6 +9,8 @@
+
+
diff --git a/Marechai.Server/Program.cs b/Marechai.Server/Program.cs
index 8595f765..786bd31e 100644
--- a/Marechai.Server/Program.cs
+++ b/Marechai.Server/Program.cs
@@ -6,12 +6,15 @@ using Marechai.Database;
using Marechai.Database.Models;
using Marechai.Helpers;
using Marechai.Server.Helpers;
+using Marechai.Server.Services;
using Markdig;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
+using Microsoft.IdentityModel.Tokens;
using Version = Marechai.Server.Interop.Version;
namespace Marechai.Server;
@@ -156,6 +159,32 @@ file class Program
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
+ builder.Services.AddAuthentication(options =>
+ {
+ options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
+ options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
+ options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
+ })
+ .AddJwtBearer(options =>
+ {
+ options.SaveToken = true;
+
+ options.TokenValidationParameters = new TokenValidationParameters
+ {
+ ClockSkew = TimeSpan.Zero,
+ ValidateIssuer = true,
+ ValidateAudience = true,
+ ValidateLifetime = false,
+ ValidateIssuerSigningKey = true,
+ ValidIssuer = "apiWithAuthBackend",
+ ValidAudience = "apiWithAuthBackend",
+ IssuerSigningKey =
+ new
+ SymmetricSecurityKey("!SomethingSecret!!SomethingSecret!!SomethingSecret!!SomethingSecret!"u8
+ .ToArray())
+ };
+ });
+
builder.Services.AddDbContextFactory(options => options.UseLazyLoadingProxies()
.UseMySql(builder.Configuration
.GetConnectionString("DefaultConnection"),
@@ -164,6 +193,12 @@ file class Program
Version(10, 5, 0)),
b => b.UseMicrosoftJson()));
+ builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true)
+ .AddRoles()
+ .AddEntityFrameworkStores();
+
+ builder.Services.AddScoped();
+
WebApplication app = builder.Build();
// Configure the HTTP request pipeline.
@@ -171,6 +206,7 @@ file class Program
app.UseHttpsRedirection();
+ app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
diff --git a/Marechai.Server/Services/TokenService.cs b/Marechai.Server/Services/TokenService.cs
new file mode 100644
index 00000000..bcdba46b
--- /dev/null
+++ b/Marechai.Server/Services/TokenService.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IdentityModel.Tokens.Jwt;
+using System.Linq;
+using System.Security.Claims;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.IdentityModel.Tokens;
+
+namespace Marechai.Server.Services;
+
+public sealed class TokenService
+{
+ public string CreateToken(IdentityUser user, IList roles)
+ {
+ JwtSecurityToken token = CreateJwtToken(CreateClaims(user, roles), CreateSigningCredentials());
+ var tokenHandler = new JwtSecurityTokenHandler();
+
+ return tokenHandler.WriteToken(token);
+ }
+
+ JwtSecurityToken CreateJwtToken(List claims, SigningCredentials credentials) =>
+ new("apiWithAuthBackend", "apiWithAuthBackend", claims, expires: null, signingCredentials: credentials);
+
+ List CreateClaims(IdentityUser user, IList roles)
+ {
+ try
+ {
+ List claims =
+ [
+ new(JwtRegisteredClaimNames.Sub, "TokenForTheApiWithAuth"),
+ new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
+ new(JwtRegisteredClaimNames.Iat,
+ EpochTime.GetIntDate(DateTime.UtcNow).ToString(CultureInfo.InvariantCulture)),
+ new(ClaimTypes.Sid, user.Id), new(ClaimTypes.Name, user.UserName), new(ClaimTypes.Email, user.Email)
+ ];
+
+ claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));
+
+ return claims;
+ }
+ catch(Exception e)
+ {
+ Console.WriteLine(e);
+
+ throw;
+ }
+ }
+
+ SigningCredentials CreateSigningCredentials() =>
+ new(new SymmetricSecurityKey("!SomethingSecret!!SomethingSecret!!SomethingSecret!!SomethingSecret!"u8
+ .ToArray()),
+ SecurityAlgorithms.HmacSha256);
+}
\ No newline at end of file