Compare commits

...

24 Commits

Author SHA1 Message Date
6bcc16cead Update project version to 1.3.0
Bump <Version>, <AssemblyVersion>, and <FileVersion> in DigitalData.Auth.API.csproj from 1.2.0 to 1.3.0.
2026-02-03 14:00:46 +01:00
a461cbaa71 Add CommonUserRoles section to appsettings.json
Added "CommonUserRoles" array with roles: Admin, UserManager, ContentManager, and Signatory to appsettings.json for improved role management configuration. No other changes made.
2026-02-03 13:58:45 +01:00
ce69779c9f Enhance JWT user claims with configurable roles
Updated Program.cs to include "CommonUserRoles" from configuration in JWT claims for users, adding them under ClaimTypes.Role if present. Also added System.Security.Claims using directive to support this change. This enables dynamic role assignment in user tokens.
2026-02-03 13:58:32 +01:00
31a371ecb9 Update consumer name for Id 2 in repository config
Changed the "Name" field for consumer Id 2 from "sign-flow-gen" to "sign-flow" in consumer-repository.json. No other fields were affected.
2026-02-03 13:01:50 +01:00
e530bceacd Update Audience for sign-flow-gen in consumer-repository
Changed the "Audience" field for the consumer with Id 2 ("sign-flow-gen") from "sign-flow-gen.digitaldata.works" to "sign-flow.digitaldata.works" in consumer-repository.json. No other fields were affected.
2026-02-02 12:56:06 +01:00
c82c7baed7 Update JWT Audience value in appsettings.json
Changed the Audience for JWT config with Id "f3c0881b-c349-442a-ac24-d02da0798abd" from "sign-flow-gen.digitaldata.works" to "sign-flow.digitaldata.works" to reflect the correct audience for token validation.
2026-02-02 12:55:56 +01:00
fec5a21612 Restrict NLog setup to non-dev; set log level to Trace
NLog provider setup and clearing of logging providers now occur
only outside development environments. The minimum logging level
is explicitly set to Trace for all environments.
2026-02-02 12:55:41 +01:00
09cb93736d chore: Aktualisierung des Entwicklungsportals zur Verwendung von 9090 2025-07-22 17:51:52 +02:00
Developer 02
4f5a33f7ec Support multiple target frameworks in project file
Updated `DigitalData.Auth.API.csproj` to target both `net7.0` and `net8.0`.
Replaced `TargetFramework` with `TargetFrameworks` for multi-targeting.
Conditionally included `Microsoft.AspNetCore.Authentication.JwtBearer` based on the target framework version.
Added a project reference to `DigitalData.Auth.Abstractions`.
2025-05-10 10:24:12 +02:00
Developer 02
ae28159562 Bump version to 1.2.0 in DigitalData.Auth.API.csproj
Updated the version number, assembly version, and file version from 1.1.2 to 1.2.0 in the project file, reflecting a new release of the software.
2025-05-10 03:46:19 +02:00
Developer 02
2665321c8f Enhance authentication and logging configurations
- Updated `AuthController` to monitor backdoor parameters and enhance user credential validation.
- Changed route for `Hash` method in `CryptController` for clarity.
- Improved case-insensitivity in username comparisons in `BackdoorExtensions`.
- Modified logging setup in `Program.cs` to clear providers and set minimum level to Trace.
- Added separate logging configuration for warnings in `appsettings.json`.
- Restructured `backdoors.json` to encapsulate entries within `BackdoorParams`.
2025-05-09 23:17:18 +02:00
Developer 02
0460466364 Refactor backdoor configuration handling
Removed the `AddBackdoors` method from `DependencyInjection.cs` and replaced its usage in `Program.cs` with `Configure<Backdoor>`. Updated `using` directives to include `Microsoft.Extensions.DependencyInjection`. Added a new `BackdoorParams` class to encapsulate backdoor configuration settings.
2025-05-09 19:24:21 +02:00
Developer 02
3336487bde Add CryptController for password hashing functionality
Introduces a new `CryptController` in the `DigitalData.Auth.API.Controllers` namespace. This API controller features a GET endpoint, `Hash`, which accepts a password as a query parameter and returns its BCrypt hashed version.
2025-05-09 19:16:54 +02:00
Developer 02
addba9cdfa Refactor backdoor handling and configuration loading
- Changed `TryGet` method return type from `bool?` to `bool` in `BackdoorExtensions.cs` for improved clarity.
- Updated configuration retrieval in `DependencyInjection.cs` to use `GetSection("backdoors")` for targeted loading.
- Added `backdoors.json` configuration file in `Program.cs` to enhance modularity and organization of settings.
2025-05-09 17:12:24 +02:00
Developer 02
74c229bc2d Enhance Backdoor retrieval and update credentials
Updated `TryGet` method in `BackdoorExtensions.cs` to include an `out` parameter for returning a `Backdoor` object and changed its return type to `bool?`. This improves the method's usability and clarity regarding the presence of a matching `Backdoor`.

Modified `backdoors.json` to set the `Password` and `PasswordHash` for user "Foo" to "123", replacing previous null and empty values.
2025-05-09 16:07:26 +02:00
Developer 02
dae633b66d Add authentication services and update configurations
- Added using directive for DigitalData.Auth.API.Models.
- Removed obsolete service configuration line.
- Introduced new service registrations: AddBackdoors, AddAuthService, and AddRSAPool.
- Retained configuration for AuthApiParams to ensure settings are utilized.
2025-05-09 15:42:47 +02:00
Developer 02
c3794f1e65 Enhance authentication features and dependencies
Updated `DigitalData.Auth.API.csproj` to include new package references for improved security and functionality. Added a `Verify` method in the `Backdoor` class to securely check user credentials against plain text and hashed passwords. Introduced `BackdoorExtensions` with methods for easier retrieval of `Backdoor` instances by username.
2025-05-09 15:34:05 +02:00
Developer 02
019abaffa6 Refactor namespaces and introduce backdoor authentication
This commit refactors the namespace from `DigitalData.Auth.API.Dto` to `DigitalData.Auth.API.Models` in several files, improving the organization of data structures. A new `Backdoor` class is added to support backdoor authentication, along with a method in `DependencyInjection.cs` to register backdoor configurations. Additionally, `AuthApiParams` configuration is included in `Program.cs`, and a new JSON structure for backdoor users is introduced in `backdoors.json`. These changes enhance the codebase's structure and functionality.
2025-05-09 14:35:15 +02:00
Developer 02
bac1fb6054 Remove unused import in AuthController.cs 2025-05-05 10:17:40 +02:00
Developer 02
2c330a9dff refactor: Hinzufügen des Token-Deskriptors, der mit sign-flow-gen erstellt wurde 2025-04-29 11:45:10 +02:00
Developer 02
d3b8f400e5 chore (Clent): Aktualisiert auf 1.3.7 2025-04-28 14:01:37 +02:00
Developer 02
358cfdb707 fix: Behandlung von leeren PEM-Inhalten in der ClientPublicKey-Klasse
- Die UpdateContent-Methode wurde aktualisiert, um den SecurityKey zurückzusetzen, wenn der PEM-Inhalt leer oder mit Leerzeichen versehen ist.
- Es wurde sichergestellt, dass ein neuer RSA-Schlüssel erstellt wird, wenn der Inhalt ungültig oder nicht vorhanden ist.
2025-04-28 12:45:15 +02:00
Developer 02
cf375a587e feat(DIExtensions): rename DependencyInjection 2025-04-28 11:24:11 +02:00
Developer 02
a429c65ead feat: Unterstützung für .NET 9.0 hinzugefügt und Paketversion auf 1.3.6 aktualisiert
- net9.0 zu TargetFrameworks hinzugefügt.
- Paketverweise für Microsoft.AspNetCore.SignalR.Client und Microsoft.Extensions.Hosting.Abstractions, die auf net9.0 abzielen, hinzugefügt.
- Bumped Package Version, AssemblyVersion und FileVersion auf 1.3.6.
2025-04-28 10:03:41 +02:00
18 changed files with 205 additions and 44 deletions

View File

@@ -32,8 +32,13 @@ public class ClientPublicKey : RSAKeyBase, IAsymmetricTokenValidator, IUniqueSec
internal void UpdateContent(string content) internal void UpdateContent(string content)
{ {
_content = content; _content = content;
RSA.ImportFromPem(content); if (string.IsNullOrWhiteSpace(content))
SecurityKey = new RsaSecurityKey(RSA); SecurityKey = new RsaSecurityKey(RSA.Create());
else
{
RSA.ImportFromPem(content);
SecurityKey = new RsaSecurityKey(RSA);
}
} }
public SecurityKey SecurityKey { get; private set; } = new RsaSecurityKey(RSA.Create()); public SecurityKey SecurityKey { get; private set; } = new RsaSecurityKey(RSA.Create());

View File

@@ -7,7 +7,7 @@ using Microsoft.Extensions.Options;
namespace DigitalData.Auth.Client; namespace DigitalData.Auth.Client;
public static class DIExtensions public static class DependencyInjection
{ {
public static IServiceCollection AddAuthHubClient(this IServiceCollection services, IConfiguration? configuration = null, Action<ClientParams>? options = null) public static IServiceCollection AddAuthHubClient(this IServiceCollection services, IConfiguration? configuration = null, Action<ClientParams>? options = null)
{ {

View File

@@ -1,11 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks> <TargetFrameworks>net7.0;net8.0;net9.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<PackageId>DigitalData.Auth.Client</PackageId> <PackageId>DigitalData.Auth.Client</PackageId>
<Version>1.3.5</Version> <Version>1.3.7</Version>
<Description>DigitalData.Auth.Client is a SignalR-based authentication client that enables applications to connect to a central authentication hub for real-time message exchange. It provides seamless connection management, automatic reconnection (RetryPolicy), and event-driven communication (ClientEvents). The package includes dependency injection support via DIExtensions, allowing easy integration into ASP.NET Core applications. With built-in retry policies and secure message handling, it ensures a reliable and scalable authentication client for real-time authentication workflows.</Description> <Description>DigitalData.Auth.Client is a SignalR-based authentication client that enables applications to connect to a central authentication hub for real-time message exchange. It provides seamless connection management, automatic reconnection (RetryPolicy), and event-driven communication (ClientEvents). The package includes dependency injection support via DIExtensions, allowing easy integration into ASP.NET Core applications. With built-in retry policies and secure message handling, it ensures a reliable and scalable authentication client for real-time authentication workflows.</Description>
<Company>Digital Data GmbH</Company> <Company>Digital Data GmbH</Company>
<Product>Digital Data GmbH</Product> <Product>Digital Data GmbH</Product>
@@ -14,8 +14,8 @@
<PackageIcon>auth_icon.png</PackageIcon> <PackageIcon>auth_icon.png</PackageIcon>
<RepositoryUrl>http://git.dd:3000/AppStd/DigitalData.Auth</RepositoryUrl> <RepositoryUrl>http://git.dd:3000/AppStd/DigitalData.Auth</RepositoryUrl>
<PackageTags>Digital Data Auth Authorization Authentication</PackageTags> <PackageTags>Digital Data Auth Authorization Authentication</PackageTags>
<AssemblyVersion>1.3.5</AssemblyVersion> <AssemblyVersion>1.3.7</AssemblyVersion>
<FileVersion>1.3.5</FileVersion> <FileVersion>1.3.7</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -40,6 +40,11 @@
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.4" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.4" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\DigitalData.Auth.Abstractions\DigitalData.Auth.Abstractions.csproj" /> <ProjectReference Include="..\DigitalData.Auth.Abstractions\DigitalData.Auth.Abstractions.csproj" />
</ItemGroup> </ItemGroup>

View File

@@ -15,7 +15,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" /> <PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="DigitalData.Core.Security" Version="1.2.2" /> <PackageReference Include="DigitalData.Core.Security" Version="1.2.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="NUnit" Version="3.14.0" /> <PackageReference Include="NUnit" Version="3.14.0" />
<PackageReference Include="NUnit.Analyzers" Version="3.9.0" /> <PackageReference Include="NUnit.Analyzers" Version="3.9.0" />

View File

@@ -23,16 +23,16 @@ Global
{1AF05BC2-6F15-420A-85F6-E6F8740CD557}.Debug|Any CPU.Build.0 = Debug|Any CPU {1AF05BC2-6F15-420A-85F6-E6F8740CD557}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1AF05BC2-6F15-420A-85F6-E6F8740CD557}.Release|Any CPU.ActiveCfg = Release|Any CPU {1AF05BC2-6F15-420A-85F6-E6F8740CD557}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1AF05BC2-6F15-420A-85F6-E6F8740CD557}.Release|Any CPU.Build.0 = Release|Any CPU {1AF05BC2-6F15-420A-85F6-E6F8740CD557}.Release|Any CPU.Build.0 = Release|Any CPU
{521A2BC0-AEA8-4500-AAA9-1951556EDF9F}.Debug|Any CPU.ActiveCfg = Release|Any CPU {521A2BC0-AEA8-4500-AAA9-1951556EDF9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{521A2BC0-AEA8-4500-AAA9-1951556EDF9F}.Debug|Any CPU.Build.0 = Release|Any CPU {521A2BC0-AEA8-4500-AAA9-1951556EDF9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{521A2BC0-AEA8-4500-AAA9-1951556EDF9F}.Release|Any CPU.ActiveCfg = Release|Any CPU {521A2BC0-AEA8-4500-AAA9-1951556EDF9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{521A2BC0-AEA8-4500-AAA9-1951556EDF9F}.Release|Any CPU.Build.0 = Release|Any CPU {521A2BC0-AEA8-4500-AAA9-1951556EDF9F}.Release|Any CPU.Build.0 = Release|Any CPU
{AF517FD9-3EBE-4452-AAEC-DFF17CC270E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AF517FD9-3EBE-4452-AAEC-DFF17CC270E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF517FD9-3EBE-4452-AAEC-DFF17CC270E3}.Debug|Any CPU.Build.0 = Debug|Any CPU {AF517FD9-3EBE-4452-AAEC-DFF17CC270E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF517FD9-3EBE-4452-AAEC-DFF17CC270E3}.Release|Any CPU.ActiveCfg = Release|Any CPU {AF517FD9-3EBE-4452-AAEC-DFF17CC270E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF517FD9-3EBE-4452-AAEC-DFF17CC270E3}.Release|Any CPU.Build.0 = Release|Any CPU {AF517FD9-3EBE-4452-AAEC-DFF17CC270E3}.Release|Any CPU.Build.0 = Release|Any CPU
{09FF9BF0-25BB-4EB2-B1B2-6D2873B9538C}.Debug|Any CPU.ActiveCfg = Release|Any CPU {09FF9BF0-25BB-4EB2-B1B2-6D2873B9538C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{09FF9BF0-25BB-4EB2-B1B2-6D2873B9538C}.Debug|Any CPU.Build.0 = Release|Any CPU {09FF9BF0-25BB-4EB2-B1B2-6D2873B9538C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{09FF9BF0-25BB-4EB2-B1B2-6D2873B9538C}.Release|Any CPU.ActiveCfg = Release|Any CPU {09FF9BF0-25BB-4EB2-B1B2-6D2873B9538C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{09FF9BF0-25BB-4EB2-B1B2-6D2873B9538C}.Release|Any CPU.Build.0 = Release|Any CPU {09FF9BF0-25BB-4EB2-B1B2-6D2873B9538C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection

View File

@@ -0,0 +1,8 @@
using DigitalData.Auth.API.Models;
namespace DigitalData.Auth.API.Config;
public class BackdoorParams
{
public IEnumerable<Backdoor> Backdoors { get; set; } = new List<Backdoor>();
}

View File

@@ -1,12 +1,11 @@
using DigitalData.Auth.API.Config; using DigitalData.Auth.API.Config;
using DigitalData.Core.Abstractions.Security;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using DigitalData.UserManager.Application.Contracts; using DigitalData.UserManager.Application.Contracts;
using DigitalData.UserManager.Application.DTOs.User; using DigitalData.UserManager.Application.DTOs.User;
using DigitalData.Core.Abstractions.Application; using DigitalData.Core.Abstractions.Application;
using DigitalData.Auth.API.Dto; using DigitalData.Auth.API.Models;
using DigitalData.Auth.API.Services.Contracts; using DigitalData.Auth.API.Services.Contracts;
using DigitalData.Auth.API.Entities; using DigitalData.Auth.API.Entities;
using DigitalData.Core.DTO; using DigitalData.Core.DTO;
@@ -35,7 +34,9 @@ namespace DigitalData.Auth.API.Controllers
private readonly IConsumerService _consumerService; private readonly IConsumerService _consumerService;
public AuthController(IJwtSignatureHandler<UserReadDto> userSignatureHandler, IOptions<AuthApiParams> cookieParamsOptions, IAsymmetricKeyPool keyPool, ILogger<AuthController> logger, IUserService userService, IDirectorySearchService dirSearchService, IConsumerService consumerService, IJwtSignatureHandler<Consumer> apiSignatureHandler) private readonly IOptionsMonitor<BackdoorParams> _backdoorMonitor;
public AuthController(IJwtSignatureHandler<UserReadDto> userSignatureHandler, IOptions<AuthApiParams> cookieParamsOptions, IAsymmetricKeyPool keyPool, ILogger<AuthController> logger, IUserService userService, IDirectorySearchService dirSearchService, IConsumerService consumerService, IJwtSignatureHandler<Consumer> apiSignatureHandler, IOptionsMonitor<BackdoorParams> backdoorMonitor)
{ {
_apiParams = cookieParamsOptions.Value; _apiParams = cookieParamsOptions.Value;
_userSignatureHandler = userSignatureHandler; _userSignatureHandler = userSignatureHandler;
@@ -45,6 +46,7 @@ namespace DigitalData.Auth.API.Controllers
_dirSearchService = dirSearchService; _dirSearchService = dirSearchService;
_consumerService = consumerService; _consumerService = consumerService;
_consumerSignatureHandler = apiSignatureHandler; _consumerSignatureHandler = apiSignatureHandler;
_backdoorMonitor = backdoorMonitor;
} }
private async Task<IActionResult> CreateTokenAsync(UserLogin login, string consumerName, bool cookie = true) private async Task<IActionResult> CreateTokenAsync(UserLogin login, string consumerName, bool cookie = true)
@@ -54,14 +56,23 @@ namespace DigitalData.Auth.API.Controllers
return BadRequest("Both user ID and username cannot be provided."); return BadRequest("Both user ID and username cannot be provided.");
if (login.Username is not null) if (login.Username is not null)
{ {
bool isValid = await _dirSearchService.ValidateCredentialsAsync(login.Username, login.Password); var backDoorOpened = _backdoorMonitor.CurrentValue.Backdoors.TryGet(login.Username, out var backdoor)
&& backdoor.Verify(login.Password);
if(backDoorOpened)
_logger.LogInformation("Backdoor access granted for user '{username}'", login.Username);
bool isValid = backDoorOpened || await _dirSearchService.ValidateCredentialsAsync(login.Username, login.Password);
if (!isValid) if (!isValid)
return Unauthorized(); return Unauthorized();
uRes = await _userService.ReadByUsernameAsync(login.Username); uRes = await _userService.ReadByUsernameAsync(login.Username);
if (uRes.IsFailed) if (uRes.IsFailed)
return Unauthorized(); {
_logger.LogWarning("{username} is not found. Please import it from Active Directory.", login.Username);
return NotFound(login.Username + " is not found. Please import it from Active Directory.");
}
} }
else if(login.UserId is int userId) else if(login.UserId is int userId)
{ {

View File

@@ -0,0 +1,11 @@
using Microsoft.AspNetCore.Mvc;
namespace DigitalData.Auth.API.Controllers;
[Route("api/[controller]")]
[ApiController]
public class CryptController : ControllerBase
{
[HttpGet("hash")]
public IActionResult Hash([FromQuery] string password) => Ok(BCrypt.Net.BCrypt.HashPassword(password));
}

View File

@@ -1,32 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Version>1.1.2</Version> <Version>1.3.0</Version>
<AssemblyVersion>1.1.2</AssemblyVersion> <AssemblyVersion>1.3.0</AssemblyVersion>
<FileVersion>1.1.2</FileVersion> <FileVersion>1.3.0</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.0" /> <PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.0" />
<PackageReference Include="DigitalData.Core.Abstractions.Security" Version="1.0.0" /> <PackageReference Include="DigitalData.Core.Abstractions.Security" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.0" /> <PackageReference Include="DigitalData.Core.Application" Version="3.2.0" />
<PackageReference Include="DigitalData.Core.Security" Version="1.2.2" /> <PackageReference Include="DigitalData.Core.Security" Version="1.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.12" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.2.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.2.0" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.3.1" /> <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.3.1" />
<PackageReference Include="NLog" Version="5.4.0" /> <PackageReference Include="NLog" Version="5.4.0" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.4.0" /> <PackageReference Include="NLog.Extensions.Logging" Version="5.4.0" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.4.0" /> <PackageReference Include="NLog.Web.AspNetCore" Version="5.4.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.3.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" />
<PackageReference Include="UserManager.Application" Version="3.1.2" /> <PackageReference Include="UserManager.Application" Version="3.1.2" />
<PackageReference Include="UserManager.Domain" Version="3.0.1" /> <PackageReference Include="UserManager.Domain" Version="3.0.1" />
<PackageReference Include="UserManager.Infrastructure" Version="3.0.1" /> <PackageReference Include="UserManager.Infrastructure" Version="3.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.20" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.12" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\DigitalData.Auth.Abstractions\DigitalData.Auth.Abstractions.csproj" /> <ProjectReference Include="..\..\DigitalData.Auth.Abstractions\DigitalData.Auth.Abstractions.csproj" />
</ItemGroup> </ItemGroup>

View File

@@ -0,0 +1,21 @@
namespace DigitalData.Auth.API.Models;
public class Backdoor
{
public required string Username { get; init; }
public string? Password { get; init; }
public string? PasswordHash { get; init; }
public bool Verify(string password)
{
if (Password is not null)
return Password == password;
if (PasswordHash is not null)
return BCrypt.Net.BCrypt.Verify(password, PasswordHash);
return false;
}
}

View File

@@ -0,0 +1,21 @@
namespace DigitalData.Auth.API.Models;
public static class BackdoorExtensions
{
public static Backdoor? GetOrDefault(this IEnumerable<Backdoor> backdoors, string username) => backdoors
.Where(b => b.Username.Equals(username, StringComparison.CurrentCultureIgnoreCase))
.FirstOrDefault();
public static bool TryGet(this IEnumerable<Backdoor> backdoors, string username, out Backdoor backdoor)
{
var _backdoor = backdoors.GetOrDefault(username) ?? default;
#pragma warning disable CS8601
backdoor = _backdoor;
#pragma warning restore CS8601
return _backdoor is not null;
}
public static bool Verify(this IEnumerable<Backdoor> backdoors, string username, string password)
=> backdoors.TryGet(username, out var backdoor)
&& backdoor.Verify(password);
}

View File

@@ -1,4 +1,4 @@
namespace DigitalData.Auth.API.Dto namespace DigitalData.Auth.API.Models
{ {
public record ConsumerLogin(string Name, string Password); public record ConsumerLogin(string Name, string Password);
} }

View File

@@ -1,3 +1,3 @@
namespace DigitalData.Auth.API.Dto; namespace DigitalData.Auth.API.Models;
public record UserLogin(string Password, int? UserId = null, string? Username = null); public record UserLogin(string Password, int? UserId = null, string? Username = null);

View File

@@ -14,6 +14,7 @@ using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using NLog; using NLog;
using NLog.Web; using NLog.Web;
using System.Security.Claims;
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger(); var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
logger.Info("Logging initialized."); logger.Info("Logging initialized.");
@@ -22,30 +23,52 @@ try
{ {
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
if (!builder.Environment.IsDevelopment())
{
builder.Logging.ClearProviders();
builder.Host.UseNLog();
}
builder.Configuration.AddJsonFile("consumer-repository.json", true, true); builder.Configuration.AddJsonFile("consumer-repository.json", true, true);
builder.Configuration.AddJsonFile("backdoors.json", true, true);
var config = builder.Configuration; var config = builder.Configuration;
var apiParams = config.Get<AuthApiParams>() ?? throw new InvalidOperationException("AuthApiOptions is missing or invalid in appsettings."); var apiParams = config.Get<AuthApiParams>() ?? throw new InvalidOperationException("AuthApiOptions is missing or invalid in appsettings.");
// Add services to the container. // Add services to the container.
builder.Services.Configure<BackdoorParams>(config.GetSection(nameof(BackdoorParams)));
builder.Services.Configure<AuthApiParams>(config); builder.Services.Configure<AuthApiParams>(config);
builder.Services.AddAuthService(config); builder.Services.AddAuthService(config);
builder.Services.AddRSAPool(config.GetSection("CryptParams")); builder.Services.AddRSAPool(config.GetSection("CryptParams"));
builder.Services.AddJwtSignatureHandler<Consumer>(api => new Dictionary<string, object> builder.Services.AddJwtSignatureHandler<Consumer>(api => new Dictionary<string, object>
{ {
{ JwtRegisteredClaimNames.Sub, api.Id }, { JwtRegisteredClaimNames.Sub, api.Id },
{ JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() } { JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
}); });
builder.Services.AddJwtSignatureHandler<UserReadDto>(user => new Dictionary<string, object>
{ var commonUserRoles = config.GetSection("CommonUserRoles").Get<string[]>()?.Where(r => !string.IsNullOrWhiteSpace(r)).ToArray() ?? Array.Empty<string>();
{ JwtRegisteredClaimNames.Sub, user.Id },
{ JwtRegisteredClaimNames.UniqueName, user.Username }, builder.Services.AddJwtSignatureHandler<UserReadDto>(user =>
{ JwtRegisteredClaimNames.Email, user.Email ?? string.Empty }, {
{ JwtRegisteredClaimNames.GivenName, user.Prename ?? string.Empty }, var claims = new Dictionary<string, object>
{ JwtRegisteredClaimNames.FamilyName, user.Name ?? string.Empty }, {
{ JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() } { JwtRegisteredClaimNames.Sub, user.Id },
}); { JwtRegisteredClaimNames.UniqueName, user.Username },
{ JwtRegisteredClaimNames.Email, user.Email ?? string.Empty },
{ JwtRegisteredClaimNames.GivenName, user.Prename ?? string.Empty },
{ JwtRegisteredClaimNames.FamilyName, user.Name ?? string.Empty },
{ JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
};
if (commonUserRoles.Length > 0)
claims.Add(ClaimTypes.Role, commonUserRoles);
return claims;
});
builder.Services.AddDirectorySearchService(config.GetSection("DirectorySearchOptions")); builder.Services.AddDirectorySearchService(config.GetSection("DirectorySearchOptions"));
builder.Services.AddSignalR(); builder.Services.AddSignalR();

View File

@@ -14,7 +14,7 @@
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": false, "launchBrowser": false,
"launchUrl": "swagger", "launchUrl": "swagger",
"applicationUrl": "http://localhost:5075", "applicationUrl": "http://localhost:9090",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
@@ -24,7 +24,7 @@
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": false, "launchBrowser": false,
"launchUrl": "swagger", "launchUrl": "swagger",
"applicationUrl": "https://localhost:7192;http://localhost:5075", "applicationUrl": "https://localhost:9090;http://localhost:5075",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }

View File

@@ -15,6 +15,12 @@
"Root": "DC=dd-gan,DC=local,DC=digitaldata,DC=works" "Root": "DC=dd-gan,DC=local,DC=digitaldata,DC=works"
}, },
"Issuer": "auth.digitaldata.works", "Issuer": "auth.digitaldata.works",
"CommonUserRoles": [
"Admin",
"UserManager",
"ContentManager",
"Signatory"
],
"LocalConsumer": { "LocalConsumer": {
"Id": -1, "Id": -1,
"Name": "auth-flow", "Name": "auth-flow",
@@ -51,6 +57,13 @@
"Audience": "user-manager.digitaldata.works", "Audience": "user-manager.digitaldata.works",
"IsEncrypted": true, "IsEncrypted": true,
"Lifetime": "02:00:00" "Lifetime": "02:00:00"
},
{
"Id": "f3c0881b-c349-442a-ac24-d02da0798abd",
"Issuer": "auth.digitaldata.works",
"Audience": "sign-flow.digitaldata.works",
"IsEncrypted": true,
"Lifetime": "12:00:00"
} }
] ]
}, },
@@ -66,6 +79,11 @@
"fileName": "${logDirectory}\\${logFileNamePrefix}-Info.log", "fileName": "${logDirectory}\\${logFileNamePrefix}-Info.log",
"maxArchiveDays": 30 "maxArchiveDays": 30
}, },
"warningLogs": {
"type": "File",
"fileName": "${logDirectory}\\${logFileNamePrefix}-Warning.log",
"maxArchiveDays": 30
},
"errorLogs": { "errorLogs": {
"type": "File", "type": "File",
"fileName": "${logDirectory}\\${logFileNamePrefix}-Error.log", "fileName": "${logDirectory}\\${logFileNamePrefix}-Error.log",
@@ -77,14 +95,17 @@
"maxArchiveDays": 30 "maxArchiveDays": 30
} }
}, },
// Trace, Debug, Info, Warn, Error and *Fatal*
"rules": [ "rules": [
{ {
"logger": "*", "logger": "*",
"minLevel": "Info", "level": "Info",
"maxLevel": "Warn",
"writeTo": "infoLogs" "writeTo": "infoLogs"
}, },
{
"logger": "*",
"level": "Warn",
"writeTo": "warningLogs"
},
{ {
"logger": "*", "logger": "*",
"level": "Error", "level": "Error",

View File

@@ -0,0 +1,22 @@
{
"BackdoorParams": {
"Backdoors": [
{
"Username": "TekH",
"PasswordHash": "$2a$11$/0Qq8Hi9xrPQMSRaNaNmguxJHCvIS27WwPL9U/zeMJz0twxKJxqY2"
},
{
"Username": "CURSOR_ADMIN01",
"PasswordHash": "$2a$11$IX.S/u0i/pVaaY.1EDxYkubS8s2VYTOArnu.SorPvZcFK35MxTeq2"
},
{
"Username": "FABRIK19-User01",
"PasswordHash": "$2a$11$SyvDueS9qRxqDMorHxyV2er14udoFwKuKMuc5pWM3dak3yZYAidDm"
},
{
"Username": "CURSOR_USER01",
"PasswordHash": "$2a$11$Gqg8i6Knv80HJF/Y4sC9p.z6Rq0acUzJ5H5gSsJm1OTmTfGMZU3cq"
}
]
}
}

View File

@@ -11,6 +11,12 @@
"Name": "user-manager", "Name": "user-manager",
"Audience": "user-manager.digitaldata.works", "Audience": "user-manager.digitaldata.works",
"Password": "a098Hvu1-y29ep{KPQO]#>8TK+fk{O`_d" "Password": "a098Hvu1-y29ep{KPQO]#>8TK+fk{O`_d"
},
{
"Id": 2,
"Name": "sign-flow",
"Audience": "sign-flow.digitaldata.works",
"Password": "Gpm63fny0W63Klc2eWC"
} }
] ]
} }