diff --git a/src/DigitalData.Auth.API/Middleware/ExceptionHandlingMiddleware.cs b/src/DigitalData.Auth.API/Middleware/ExceptionHandlingMiddleware.cs
new file mode 100644
index 0000000..d89e728
--- /dev/null
+++ b/src/DigitalData.Auth.API/Middleware/ExceptionHandlingMiddleware.cs
@@ -0,0 +1,99 @@
+using DigitalData.Core.Exceptions;
+using Microsoft.AspNetCore.Mvc;
+using System.Net;
+
+namespace DigitalData.Auth.API.Middleware;
+
+///
+/// Middleware for handling exceptions globally in the application.
+/// Captures exceptions thrown during the request pipeline execution,
+/// logs them, and returns an appropriate HTTP response with a JSON error details.
+///
+public class ExceptionHandlingMiddleware
+{
+ private readonly RequestDelegate _next;
+ private readonly ILogger _logger;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The next middleware in the request pipeline.
+ /// The logger instance for logging exceptions.
+ public ExceptionHandlingMiddleware(RequestDelegate next, ILogger logger)
+ {
+ _next = next;
+ _logger = logger;
+ }
+
+ ///
+ /// Invokes the middleware to handle the HTTP request.
+ ///
+ /// The HTTP context of the current request.
+ /// A task that represents the asynchronous operation.
+ public async Task InvokeAsync(HttpContext context)
+ {
+ try
+ {
+ await _next(context); // Continue down the pipeline
+ }
+ catch (Exception ex)
+ {
+ await HandleExceptionAsync(context, ex, _logger);
+ }
+ }
+
+ ///
+ /// Handles exceptions by logging them and writing an appropriate JSON response.
+ ///
+ /// The HTTP context of the current request.
+ /// The exception that occurred.
+ /// The logger instance for logging the exception.
+ /// A task that represents the asynchronous operation.
+ private static async Task HandleExceptionAsync(HttpContext context, Exception exception, ILogger logger)
+ {
+ context.Response.ContentType = "application/json";
+
+ ValidationProblemDetails? details = null;
+
+ switch (exception)
+ {
+ case BadRequestException badRequestEx:
+ if (badRequestEx.InnerException is not null)
+ {
+ logger.LogError(
+ badRequestEx.InnerException,
+ "BadRequestException inner exception captured.");
+ }
+
+ context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
+ details = new()
+ {
+ Title = "Bad Procedure",
+ Detail = badRequestEx.Message
+ };
+ break;
+
+ case NotFoundException notFoundEx:
+ context.Response.StatusCode = (int)HttpStatusCode.NotFound;
+ details = new()
+ {
+ Title = "Not Found",
+ Detail = notFoundEx.Message
+ };
+ break;
+
+ default:
+ logger.LogError(exception, "Unhandled exception occurred.");
+ context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
+ details = new()
+ {
+ Title = "Internal Server Error",
+ Detail = "An unexpected error occurred. Please try again later."
+ };
+ break;
+ }
+
+ if (details is not null)
+ await context.Response.WriteAsJsonAsync(details);
+ }
+}
\ No newline at end of file
diff --git a/src/DigitalData.Auth.API/Program.cs b/src/DigitalData.Auth.API/Program.cs
index a9fbc07..9a50a02 100644
--- a/src/DigitalData.Auth.API/Program.cs
+++ b/src/DigitalData.Auth.API/Program.cs
@@ -1,6 +1,7 @@
using DigitalData.Auth.API.Config;
using DigitalData.Auth.API.Entities;
using DigitalData.Auth.API.Hubs;
+using DigitalData.Auth.API.Middleware;
using DigitalData.Auth.API.Services;
using DigitalData.Core.Abstractions.Security.Extensions;
using DigitalData.Core.Abstractions.Security.Services;
@@ -78,6 +79,8 @@ try
var cnn_str = builder.Configuration.GetConnectionString("Default") ?? throw new InvalidOperationException("Default connection string is not found.");
+ builder.Services.AddLocalization();
+
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
@@ -174,6 +177,8 @@ try
var app = builder.Build();
+ app.UseMiddleware();
+
issuerSigningKeyInitiator = new Lazy(() =>
{
var factory = app.Services.GetRequiredService();