This commit is contained in:
Developer01 2025-05-07 16:51:02 +02:00
commit dc4b5bade0
13 changed files with 264 additions and 198 deletions

View File

@ -13,7 +13,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.1" />
<PackageReference Include="DigitalData.Core.Client" Version="2.0.3" />
<PackageReference Include="DigitalData.Core.DTO" Version="2.0.1" />

View File

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher.Abstraction" Version="3.0.0" />
<PackageReference Include="UserManager.Domain" Version="3.0.2" />
</ItemGroup>

View File

@ -1,23 +1,20 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.UserManager.Application.Contracts;
using DigitalData.UserManager.Application.DTOs.User;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using DigitalData.UserManager.Application.DTOs.Auth;
using Microsoft.AspNetCore.Authorization;
using EnvelopeGenerator.GeneratorAPI.Models;
namespace EnvelopeGenerator.GeneratorAPI.Controllers
namespace EnvelopeGenerator.GeneratorAPI.Controllers;
/// <summary>
/// Controller verantwortlich für die Benutzer-Authentifizierung, einschließlich Anmelden, Abmelden und Überprüfung des Authentifizierungsstatus.
/// </summary>
[Route("api/[controller]")]
[ApiController]
public partial class AuthController : ControllerBase
{
/// <summary>
/// Controller verantwortlich für die Benutzer-Authentifizierung, einschließlich Anmelden, Abmelden und Überprüfung des Authentifizierungsstatus.
/// </summary>
[Route("api/[controller]")]
[ApiController]
public partial class AuthController : ControllerBase
{
private readonly ILogger<AuthController> _logger;
private readonly IUserService _userService;
private readonly IDirectorySearchService _dirSearchService;
@ -65,58 +62,10 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
[AllowAnonymous]
[HttpPost]
public async Task<IActionResult> Login([FromBody] Login login, [FromQuery] bool cookie = false)
public Task<IActionResult> Login([FromBody] Login login, [FromQuery] bool cookie = false)
{
try
{
bool isValid = _dirSearchService.ValidateCredentials(login.Username, login.Password);
if (!isValid)
return Unauthorized();
//find the user
var uRes = await _userService.ReadByUsernameAsync(login.Username);
if (!uRes.IsSuccess || uRes.Data is null)
{
return Forbid();
}
UserReadDto user = uRes.Data;
// Create claims
var claims = new List<Claim>
{
new (ClaimTypes.NameIdentifier, user.Id.ToString()),
new (ClaimTypes.Name, user.Username),
new (ClaimTypes.Surname, user.Name!),
new (ClaimTypes.GivenName, user.Prename!),
new (ClaimTypes.Email, user.Email!),
};
// Create claimsIdentity
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
// Create authProperties
var authProperties = new AuthenticationProperties
{
IsPersistent = true,
AllowRefresh = true,
ExpiresUtc = DateTime.Now.AddMinutes(180)
};
// Sign in
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
return Ok();
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error occurred.\n{ErrorMessage}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
// added to configure open API (swagger and scalar)
throw new NotImplementedException();
}
/// <summary>
@ -143,9 +92,10 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
[AllowAnonymous]
[HttpPost]
[Route("form")]
public async Task<IActionResult> Login([FromForm] Login login)
public Task<IActionResult> Login([FromForm] Login login)
{
return await Login(login, true);
// added to configure open API (swagger and scalar)
throw new NotImplementedException();
}
/// <summary>
@ -197,5 +147,4 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
[Authorize]
[HttpGet]
public IActionResult IsAuthenticated() => Ok();
}
}

View File

@ -19,12 +19,13 @@
<ItemGroup>
<PackageReference Include="AspNetCore.Scalar" Version="1.1.8" />
<PackageReference Include="DigitalData.Auth.Client" Version="1.3.7" />
<PackageReference Include="DigitalData.Core.API" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.3" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.4" />
<PackageReference Include="Scalar.AspNetCore" Version="2.1.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" />
<PackageReference Include="Scalar.AspNetCore" Version="2.2.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.1" />
<PackageReference Include="DigitalData.Core.DTO" Version="2.0.1" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher.Abstraction" Version="3.0.0" />

View File

@ -0,0 +1,10 @@
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'dotnet build'
}
}
}
}

View File

@ -0,0 +1,28 @@
namespace EnvelopeGenerator.GeneratorAPI.Models;
/// <summary>
/// Represents the keys and default values used for authentication token handling
/// within the Envelope Generator API.
/// </summary>
public class AuthTokenKeys
{
/// <summary>
/// Gets the name of the cookie used to store the authentication token.
/// </summary>
public string Cookie { get; init; } = "AuthToken";
/// <summary>
/// Gets the name of the query string parameter used to pass the authentication token.
/// </summary>
public string QueryString { get; init; } = "AuthToken";
/// <summary>
/// Gets the expected issuer value for the authentication token.
/// </summary>
public string Issuer { get; init; } = "auth.digitaldata.works";
/// <summary>
/// Gets the expected audience value for the authentication token.
/// </summary>
public string Audience { get; init; } = "sign-flow-gen.digitaldata.works";
}

View File

@ -1,6 +1,5 @@
using DigitalData.Core.API;
using DigitalData.Core.Application;
using DigitalData.UserManager.Application;
using EnvelopeGenerator.Infrastructure;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Localization;
@ -10,11 +9,19 @@ using Scalar.AspNetCore;
using Microsoft.OpenApi.Models;
using DigitalData.UserManager.DependencyInjection;
using EnvelopeGenerator.Application;
using DigitalData.Auth.Client;
using DigitalData.Core.Abstractions;
using EnvelopeGenerator.GeneratorAPI.Models;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using DigitalData.Core.Abstractions.Security.Extensions;
var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration;
var deferredProvider = new DeferredServiceProvider();
builder.Services.AddControllers();
//CORS Policy
@ -85,6 +92,49 @@ builder.Services.AddOpenApi();
var connStr = config.GetConnectionString("Default") ?? throw new InvalidOperationException("There is no default connection string in appsettings.json.");
builder.Services.AddDbContext<EGDbContext>(options => options.UseSqlServer(connStr));
builder.Services.AddAuthHubClient(config.GetSection("AuthClientParams"));
var authTokenKeys = config.GetOrDefault<AuthTokenKeys>();
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(opt =>
{
opt.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKeyResolver = (token, securityToken, identifier, parameters) =>
{
var clientParams = deferredProvider.GetOptions<ClientParams>();
var publicKey = clientParams!.PublicKeys.Get(authTokenKeys.Issuer, authTokenKeys.Audience);
return new List<SecurityKey>() { publicKey.SecurityKey };
},
ValidateIssuer = true,
ValidIssuer = authTokenKeys.Issuer,
ValidateAudience = true,
ValidAudience = authTokenKeys.Audience,
};
opt.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
// if there is no token read related cookie or query string
if (context.Token is null) // if there is no token
{
if (context.Request.Cookies.TryGetValue(authTokenKeys.Cookie, out var cookieToken) && cookieToken is not null)
context.Token = cookieToken;
else if (context.Request.Query.TryGetValue(authTokenKeys.QueryString, out var queryStrToken))
context.Token = queryStrToken;
}
return Task.CompletedTask;
}
};
});
// Authentication
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
@ -114,6 +164,8 @@ builder.Services
var app = builder.Build();
deferredProvider.Factory = () => app.Services;
app.MapOpenApi();
// Configure the HTTP request pipeline.

View File

@ -4,5 +4,15 @@
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AuthClientParams": {
"Url": "https://localhost:7192/auth-hub",
"PublicKeys": [
{
"Issuer": "auth.digitaldata.works",
"Audience": "sign-flow-gen.digitaldata.works"
}
],
"RetryDelay": "00:00:05"
}
}

View File

@ -20,5 +20,21 @@
"User": "(&(objectClass=user)(sAMAccountName=*))",
"Group": "(&(objectClass=group)(samAccountName=*))"
}
},
"AuthClientParams": {
"Url": "https://localhost:7192/auth-hub",
"PublicKeys": [
{
"Issuer": "auth.digitaldata.works",
"Audience": "sign-flow-gen.digitaldata.works"
}
],
"RetryDelay": "00:00:05"
},
"AuthTokenKeys": {
"Cookie": "AuthToken",
"QueryString": "AuthToken",
"Issuer": "auth.digitaldata.works",
"Audience": "work-flow.digitaldata.works"
}
}

View File

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.Infrastructure" Version="2.0.4" />
<PackageReference Include="DigitalData.Core.Infrastructure.AutoMapper" Version="1.0.2" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.0.0" />

View File

@ -19,7 +19,7 @@
<PackageReference Include="CommandDotNet" Version="7.0.5" />
<PackageReference Include="CommandDotNet.IoC.MicrosoftDependencyInjection" Version="5.0.1" />
<PackageReference Include="CommandDotNet.NameCasing" Version="4.0.2" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.20" />
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="7.0.20" />

View File

@ -23,7 +23,7 @@
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.API" Version="2.1.1" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.20" />

View File

@ -2101,7 +2101,7 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="BuildBundlerMinifier2022" Version="2.9.9" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.API" Version="2.1.1" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.1" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.0.0" />