Unnötige Paketverweise wurden aus dem API-Projekt entfernt, einschließlich Entity Framework Core und System.DirectoryServices. Ersetzte `AddDbContext` durch `AddUserManager` in `Program.cs`, um die UserManager-Dienstkonfiguration zu rationalisieren. Die Datei `Extensions.cs` wurde aktualisiert, um die Überladung der Verbindungszeichenfolge für `AddUserManager` zu entfernen, und `DependencyInjection.cs` wurde geändert, um die Einrichtung der UserManager-Infrastruktur zu vereinfachen.
218 lines
8.3 KiB
C#
218 lines
8.3 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using DigitalData.UserManager.Infrastructure.Repositories;
|
|
using DigitalData.UserManager.Application;
|
|
using DigitalData.Core.Application;
|
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
|
using NLog.Web;
|
|
using NLog;
|
|
using DigitalData.Core.API;
|
|
using DigitalData.UserManager.API.Controllers;
|
|
using DigitalData.UserManager.Application.Services;
|
|
using Microsoft.Data.SqlClient;
|
|
using Newtonsoft.Json;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
using DigitalData.UserManager.Application.DTOs.User;
|
|
using DigitalData.UserManager.API.Models;
|
|
using DigitalData.Auth.Client;
|
|
using DigitalData.UserManager.API;
|
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|
using Microsoft.Extensions.Options;
|
|
using DigitalData.Core.Abstractions.Security.Extensions;
|
|
using Microsoft.OpenApi.Models;
|
|
using DigitalData.UserManager.DependencyInjection;
|
|
|
|
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
|
|
logger.Debug("init main");
|
|
|
|
try {
|
|
var builder = WebApplication.CreateBuilder();
|
|
|
|
var config = builder.Configuration;
|
|
|
|
builder.Services.AddEncryptor(builder.Configuration.GetSection("EncryptionParameters"));
|
|
|
|
if (builder.Configuration.GetValue<bool>("RunAsWindowsService"))
|
|
builder.Host.UseWindowsService();
|
|
|
|
builder.Logging.ClearProviders();
|
|
builder.Host.UseNLog();
|
|
|
|
builder.Services.AddControllers(opt =>
|
|
{
|
|
opt.Conventions.Add(new RemoveIfControllerConvention()
|
|
.AndIf(c => c.ControllerName == nameof(EncryptionController).Replace("Controller", ""))
|
|
.AndIf(c => !config.GetValue<bool>("UseEncryptor")));
|
|
}).AddNewtonsoftJson(options =>
|
|
{
|
|
options.SerializerSettings.DateTimeZoneHandling = config.GetValue<DateTimeZoneHandling>("DateTimeZoneHandling");
|
|
});
|
|
|
|
if (builder.Configuration.GetValue<bool>("UseSwagger"))
|
|
{
|
|
builder.Services.AddEndpointsApiExplorer();
|
|
builder.Services.AddSwaggerGen();
|
|
}
|
|
|
|
builder.Services.AddControllers(opt =>
|
|
{
|
|
opt.Conventions.Add(new RemoveIfControllerConvention()
|
|
.AndIf(c => c.ControllerName == nameof(EncryptionController).Replace("Controller", ""))
|
|
.AndIf(c => !config.GetValue<bool>("UseEncryptor")));
|
|
});
|
|
|
|
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
|
.AddCookie(options =>
|
|
{
|
|
options.Cookie.HttpOnly = true; // Makes the cookie inaccessible to client-side scripts for security
|
|
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; // Ensures cookies are sent over HTTPS only
|
|
options.Cookie.SameSite = SameSiteMode.Strict; // Protects against CSRF attacks by restricting how cookies are sent with requests from external sites
|
|
options.LoginPath = "/api/auth/login";
|
|
options.LogoutPath = "/api/auth/logout";
|
|
});
|
|
|
|
// Once the app is built, the password will be decrypted with Encryptor. lazy loading also acts as a call back method.
|
|
Lazy<string>? cnn_str = null;
|
|
|
|
builder.Services.AddUserManager(options => options.UseSqlServer(cnn_str!.Value).EnableSensitiveDataLogging());
|
|
|
|
var allowedOrigins = builder.Configuration.GetSection("AllowedOrigins").Get<string[]>() ?? throw new InvalidOperationException("In appsettings there is no allowed origin.");
|
|
|
|
builder.Services.AddCors(options =>
|
|
{
|
|
options.AddPolicy(name: "DefaultCorsPolicy",
|
|
builder =>
|
|
{
|
|
builder.WithOrigins(allowedOrigins)
|
|
.AllowAnyMethod()
|
|
.AllowAnyHeader()
|
|
.AllowCredentials();
|
|
});
|
|
});
|
|
|
|
builder.ConfigureBySection<DirectorySearchOptions>();
|
|
builder.Services.AddDirectorySearchService(config.GetSection("DirectorySearchOptions"));
|
|
builder.Services.AddJWTService<UserReadDto>(user => new SecurityTokenDescriptor()
|
|
{
|
|
Claims = user.ToClaimList().ToDictionary(claim => claim.Type, claim => claim.Value as object)
|
|
});
|
|
|
|
var lazyProvider = new LazyServiceProvider();
|
|
|
|
builder.Services.AddAuthHubClient(config.GetSection("AuthClientParams"));
|
|
|
|
var authTokenKeys = config.GetSection(nameof(AuthTokenKeys)).Get<AuthTokenKeys>() ?? new();
|
|
|
|
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 = lazyProvider.GetRequiredService<IOptions<ClientParams>>()?.Value;
|
|
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;
|
|
}
|
|
};
|
|
});
|
|
|
|
builder.Services.AddSwaggerGen(setupAct =>
|
|
{
|
|
setupAct.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
|
{
|
|
Description = "JWT Authorization header using the Bearer scheme. Example: \"Bearer {token}\"",
|
|
Name = "Authorization",
|
|
In = ParameterLocation.Header,
|
|
Type = SecuritySchemeType.Http,
|
|
Scheme = "Bearer"
|
|
});
|
|
|
|
setupAct.AddSecurityRequirement(new OpenApiSecurityRequirement
|
|
{
|
|
{
|
|
new OpenApiSecurityScheme
|
|
{
|
|
Reference = new OpenApiReference
|
|
{
|
|
Type = ReferenceType.SecurityScheme,
|
|
Id = "Bearer"
|
|
}
|
|
},
|
|
Array.Empty<string>()
|
|
}
|
|
});
|
|
});
|
|
|
|
builder.Services.AddCookieBasedLocalizer();
|
|
|
|
var app = builder.Build();
|
|
|
|
lazyProvider.Factory = () => app.Services;
|
|
|
|
cnn_str = new(() =>
|
|
{
|
|
var encryptor = app.Services.GetRequiredService<Encryptor>();
|
|
var eCnnStr = config.GetConnectionString("UM_DEF") ?? throw new InvalidOperationException("Connection string 'DD_ECM_Connection' is missing from the configuration.");
|
|
|
|
SqlConnectionStringBuilder cnnStrBuilder = new(eCnnStr);
|
|
cnnStrBuilder.UserID = encryptor.Decrypt(cnnStrBuilder.UserID);
|
|
cnnStrBuilder.Password = encryptor.Decrypt(cnnStrBuilder.Password);
|
|
var dCnnStr = cnnStrBuilder.ConnectionString;
|
|
return dCnnStr;
|
|
});
|
|
|
|
app.UseCors("DefaultCorsPolicy");
|
|
|
|
if (builder.Configuration.GetValue<bool>("UseSwagger"))
|
|
{
|
|
app.UseSwagger();
|
|
app.UseSwaggerUI();
|
|
}
|
|
|
|
app.UseCookieBasedLocalizer("de-DE", "en-US");
|
|
|
|
app.UseDefaultFiles();
|
|
app.UseStaticFiles();
|
|
|
|
app.UseRouting();
|
|
app.UseHttpsRedirection();
|
|
app.UseAuthentication();
|
|
app.UseAuthorization();
|
|
|
|
app.MapControllers();
|
|
|
|
app.MapDefaultControllerRoute();
|
|
|
|
app.Run();
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
logger.Error(exception, "Stopped program because of exception");
|
|
throw;
|
|
} |