Index: ChapterX.API/Controllers/AdminsController.cs
===================================================================
--- ChapterX.API/Controllers/AdminsController.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.API/Controllers/AdminsController.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -40,5 +40,5 @@
 
         [HttpPost]
-        [Authorize]
+        [Authorize(Roles = "Admin")]
         public async Task<ActionResult> Add([FromBody] AddRequest request)
         {
@@ -49,5 +49,5 @@
 
         [HttpPut("{id:int}")]
-        [Authorize]
+        [Authorize(Roles = "Admin")]
         public async Task<ActionResult> Update(int id, [FromBody] UpdateRequest request)
         {
@@ -63,5 +63,5 @@
 
         [HttpDelete("{id:int}")]
-        [Authorize]
+        [Authorize(Roles = "Admin")]
         public async Task<ActionResult> Delete(int id)
         {
Index: ChapterX.API/Controllers/ChaptersController.cs
===================================================================
--- ChapterX.API/Controllers/ChaptersController.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.API/Controllers/ChaptersController.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -5,4 +5,6 @@
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Logging;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
 
 namespace ChapterX.API.Controllers
@@ -40,4 +42,5 @@
 
         [HttpPost]
+        [Authorize]
         public async Task<ActionResult> Add([FromBody] AddRequest request)
         {
@@ -57,5 +60,6 @@
             }
 
-            var response = await _mediator.Send(request);
+            var callerId = int.Parse(User.FindFirstValue(JwtRegisteredClaimNames.Sub)!);
+            var response = await _mediator.Send(request with { CallerId = callerId });
             return Ok(response);
         }
@@ -66,5 +70,6 @@
         {
             _logger.LogInformation("Deleting chapter with ID: {ChapterId}", id);
-            var response = await _mediator.Send(new DeleteRequest(id));
+            var callerId = int.Parse(User.FindFirstValue(JwtRegisteredClaimNames.Sub)!);
+            var response = await _mediator.Send(new DeleteRequest(id, callerId));
             return Ok(response);
         }
Index: ChapterX.API/Controllers/CommentsController.cs
===================================================================
--- ChapterX.API/Controllers/CommentsController.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.API/Controllers/CommentsController.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -6,4 +6,6 @@
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Logging;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
 
 namespace ChapterX.API.Controllers
@@ -63,6 +65,7 @@
         public async Task<ActionResult> Add([FromBody] AddRequest request)
         {
+            var callerId = int.Parse(User.FindFirstValue(JwtRegisteredClaimNames.Sub)!);
             _logger.LogInformation("Adding a new comment");
-            var response = await _mediator.Send(request);
+            var response = await _mediator.Send(request with { UserId = callerId });
             return Ok(response);
         }
@@ -78,5 +81,6 @@
             }
 
-            var response = await _mediator.Send(request);
+            var callerId = int.Parse(User.FindFirstValue(JwtRegisteredClaimNames.Sub)!);
+            var response = await _mediator.Send(request with { CallerId = callerId });
             return Ok(response);
         }
@@ -87,5 +91,6 @@
         {
             _logger.LogInformation("Deleting comment with ID: {CommentId}", id);
-            var response = await _mediator.Send(new DeleteRequest(id));
+            var callerId = int.Parse(User.FindFirstValue(JwtRegisteredClaimNames.Sub)!);
+            var response = await _mediator.Send(new DeleteRequest(id, callerId));
             return Ok(response);
         }
Index: ChapterX.API/Controllers/StoriesController.cs
===================================================================
--- ChapterX.API/Controllers/StoriesController.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.API/Controllers/StoriesController.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -5,4 +5,6 @@
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Logging;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
 
 namespace ChapterX.API.Controllers
@@ -46,6 +48,7 @@
         public async Task<ActionResult> Add([FromBody] AddRequest request)
         {
-            _logger.LogInformation("Adding a new story for UserId: {UserId}", request.UserId);
-            var response = await _mediator.Send(request);
+            var callerId = int.Parse(User.FindFirstValue(JwtRegisteredClaimNames.Sub)!);
+            _logger.LogInformation("Adding a new story for UserId: {UserId}", callerId);
+            var response = await _mediator.Send(request with { UserId = callerId });
             return Ok(response);
         }
@@ -62,5 +65,6 @@
             }
 
-            var response = await _mediator.Send(request);
+            var callerId = int.Parse(User.FindFirstValue(JwtRegisteredClaimNames.Sub)!);
+            var response = await _mediator.Send(request with { CallerId = callerId });
             return Ok(response);
         }
@@ -72,5 +76,6 @@
         {
             _logger.LogInformation("Deleting story with ID: {StoryId}", id);
-            var response = await _mediator.Send(new DeleteRequest(id));
+            var callerId = int.Parse(User.FindFirstValue(JwtRegisteredClaimNames.Sub)!);
+            var response = await _mediator.Send(new DeleteRequest(id, callerId));
             return Ok(response);
         }
Index: ChapterX.API/Controllers/UsersController.cs
===================================================================
--- ChapterX.API/Controllers/UsersController.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.API/Controllers/UsersController.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -5,4 +5,6 @@
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Logging;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
 
 namespace ChapterX.API.Controllers
@@ -67,4 +69,9 @@
             }
 
+            var callerId = int.Parse(User.FindFirstValue(JwtRegisteredClaimNames.Sub)!);
+            var isAdmin = User.IsInRole("Admin");
+            if (callerId != id && !isAdmin)
+                return Forbid();
+
             var response = await _mediator.Send(request);
             return Ok(response);
@@ -76,4 +83,9 @@
         {
             _logger.LogInformation("Deleting user with ID: {UserId}", id);
+            var callerId = int.Parse(User.FindFirstValue(JwtRegisteredClaimNames.Sub)!);
+            var isAdmin = User.IsInRole("Admin");
+            if (callerId != id && !isAdmin)
+                return Forbid();
+
             var response = await _mediator.Send(new DeleteRequest(id));
             return Ok(response);
Index: ChapterX.API/Program.cs
===================================================================
--- ChapterX.API/Program.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.API/Program.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -7,4 +7,8 @@
 
 var builder = WebApplication.CreateBuilder(args);
+
+var jwtKey = builder.Configuration["Jwt:Key"];
+if (string.IsNullOrWhiteSpace(jwtKey) || jwtKey.StartsWith("change-this"))
+    throw new InvalidOperationException("Jwt:Key is not configured. Set it via environment variable DOTNET_Jwt__Key before starting the application.");
 
 builder.Services.AddCors(options =>
@@ -85,4 +89,6 @@
     ctx.Response.ContentType = "application/json";
 
+    var logger = ctx.RequestServices.GetRequiredService<ILogger<Program>>();
+
     string message;
     int status;
@@ -107,10 +113,14 @@
             message = "A user with this email or username already exists.";
         else
-            message = "Database error: " + inner;
+        {
+            logger.LogError(dbEx, "Unhandled database error");
+            message = "A database error occurred. Please try again.";
+        }
     }
     else
     {
+        logger.LogError(ex, "Unhandled exception");
         status = 500;
-        message = ex?.Message ?? "An error occurred.";
+        message = "An unexpected error occurred.";
     }
 
