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.";
     }
 
Index: ChapterX.Application/Auth/LoginRequest.cs
===================================================================
--- ChapterX.Application/Auth/LoginRequest.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Auth/LoginRequest.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -1,6 +1,10 @@
 using MediatR;
+using System.ComponentModel.DataAnnotations;
 
 namespace ChapterX.Application.Auth
 {
-    public record LoginRequest(string Email, string Password) : IRequest<LoginResponse>;
+    public record LoginRequest(
+        [Required][EmailAddress][MaxLength(200)] string Email,
+        [Required][MaxLength(128)] string Password
+    ) : IRequest<LoginResponse>;
 }
Index: ChapterX.Application/Auth/RegisterRequest.cs
===================================================================
--- ChapterX.Application/Auth/RegisterRequest.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Auth/RegisterRequest.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -1,6 +1,13 @@
 using MediatR;
+using System.ComponentModel.DataAnnotations;
 
 namespace ChapterX.Application.Auth
 {
-    public record RegisterRequest(string Username, string Email, string Name, string Surname, string Password) : IRequest<RegisterResponse>;
+    public record RegisterRequest(
+        [Required][MaxLength(50)] string Username,
+        [Required][EmailAddress][MaxLength(200)] string Email,
+        [Required][MaxLength(100)] string Name,
+        [Required][MaxLength(100)] string Surname,
+        [Required][MinLength(8)][MaxLength(128)] string Password
+    ) : IRequest<RegisterResponse>;
 }
Index: ChapterX.Application/Chapter/Commands/AddRequest.cs
===================================================================
--- ChapterX.Application/Chapter/Commands/AddRequest.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Chapter/Commands/AddRequest.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -1,11 +1,12 @@
 using MediatR;
+using System.ComponentModel.DataAnnotations;
 
 namespace ChapterX.Application.Chapter.Commands
 {
     public record AddRequest(
-        int Number,
-        string Name,
-        string Title,
-        string Content,
+        [Range(1, int.MaxValue)] int Number,
+        [Required][MaxLength(200)] string Name,
+        [Required][MaxLength(300)] string Title,
+        [Required] string Content,
         int StoryId
     ) : IRequest<AddResponse>;
Index: ChapterX.Application/Chapter/Commands/DeleteHandler.cs
===================================================================
--- ChapterX.Application/Chapter/Commands/DeleteHandler.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Chapter/Commands/DeleteHandler.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -18,7 +18,10 @@
         public async Task<DeleteResponse> Handle(DeleteRequest request, CancellationToken cancellationToken)
         {
-            var chapter = await _chapterRepository.GetByIdAsync(request.Id, cancellationToken);
+            var chapter = await _chapterRepository.GetByIdWithStoryAsync(request.Id, cancellationToken);
             if (chapter is null)
                 return new DeleteResponse(false);
+
+            if (chapter.Story.UserId != request.CallerId)
+                throw new UnauthorizedAccessException("You do not own this chapter.");
 
             await _chapterRepository.DeleteAsync(chapter, cancellationToken);
Index: ChapterX.Application/Chapter/Commands/DeleteRequest.cs
===================================================================
--- ChapterX.Application/Chapter/Commands/DeleteRequest.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Chapter/Commands/DeleteRequest.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -3,4 +3,4 @@
 namespace ChapterX.Application.Chapter.Commands
 {
-    public record DeleteRequest(int Id) : IRequest<DeleteResponse>;
+    public record DeleteRequest(int Id, int CallerId) : IRequest<DeleteResponse>;
 }
Index: ChapterX.Application/Chapter/Commands/UpdateHandler.cs
===================================================================
--- ChapterX.Application/Chapter/Commands/UpdateHandler.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Chapter/Commands/UpdateHandler.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -18,7 +18,10 @@
         public async Task<UpdateResponse> Handle(UpdateRequest request, CancellationToken cancellationToken)
         {
-            var chapter = await _chapterRepository.GetByIdAsync(request.Id, cancellationToken);
+            var chapter = await _chapterRepository.GetByIdWithStoryAsync(request.Id, cancellationToken);
             if (chapter is null)
                 return new UpdateResponse(false);
+
+            if (chapter.Story.UserId != request.CallerId)
+                throw new UnauthorizedAccessException("You do not own this chapter.");
 
             chapter.Number = request.Number;
Index: ChapterX.Application/Chapter/Commands/UpdateRequest.cs
===================================================================
--- ChapterX.Application/Chapter/Commands/UpdateRequest.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Chapter/Commands/UpdateRequest.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -9,5 +9,6 @@
         string Title,
         string Content,
-        int? WordCount
+        int? WordCount,
+        int CallerId = 0
     ) : IRequest<UpdateResponse>;
 }
Index: ChapterX.Application/Comment/Commands/AddRequest.cs
===================================================================
--- ChapterX.Application/Comment/Commands/AddRequest.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Comment/Commands/AddRequest.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -1,6 +1,11 @@
 using MediatR;
+using System.ComponentModel.DataAnnotations;
 
 namespace ChapterX.Application.Comment.Commands
 {
-    public record AddRequest(string Content, int UserId, int StoryId) : IRequest<AddResponse>;
+    public record AddRequest(
+        [Required][MaxLength(2000)] string Content,
+        int UserId,
+        int StoryId
+    ) : IRequest<AddResponse>;
 }
Index: ChapterX.Application/Comment/Commands/DeleteHandler.cs
===================================================================
--- ChapterX.Application/Comment/Commands/DeleteHandler.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Comment/Commands/DeleteHandler.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -22,4 +22,7 @@
                 return new DeleteResponse(false);
 
+            if (comment.UserId != request.CallerId)
+                throw new UnauthorizedAccessException("You do not own this comment.");
+
             await _commentRepository.DeleteAsync(comment, cancellationToken);
 
Index: ChapterX.Application/Comment/Commands/DeleteRequest.cs
===================================================================
--- ChapterX.Application/Comment/Commands/DeleteRequest.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Comment/Commands/DeleteRequest.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -3,4 +3,4 @@
 namespace ChapterX.Application.Comment.Commands
 {
-    public record DeleteRequest(int Id) : IRequest<DeleteResponse>;
+    public record DeleteRequest(int Id, int CallerId) : IRequest<DeleteResponse>;
 }
Index: ChapterX.Application/Comment/Commands/UpdateHandler.cs
===================================================================
--- ChapterX.Application/Comment/Commands/UpdateHandler.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Comment/Commands/UpdateHandler.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -22,4 +22,7 @@
                 return new UpdateResponse(false);
 
+            if (comment.UserId != request.CallerId)
+                throw new UnauthorizedAccessException("You do not own this comment.");
+
             comment.Content = request.Content;
             comment.UpdatedAt = DateTime.UtcNow;
Index: ChapterX.Application/Comment/Commands/UpdateRequest.cs
===================================================================
--- ChapterX.Application/Comment/Commands/UpdateRequest.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Comment/Commands/UpdateRequest.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -3,4 +3,4 @@
 namespace ChapterX.Application.Comment.Commands
 {
-    public record UpdateRequest(int Id, string Content) : IRequest<UpdateResponse>;
+    public record UpdateRequest(int Id, string Content, int CallerId = 0) : IRequest<UpdateResponse>;
 }
Index: ChapterX.Application/Story/Commands/AddRequest.cs
===================================================================
--- ChapterX.Application/Story/Commands/AddRequest.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Story/Commands/AddRequest.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -1,6 +1,14 @@
 using MediatR;
+using System.ComponentModel.DataAnnotations;
 
 namespace ChapterX.Application.Story.Commands
 {
-    public record AddRequest(bool MatureContent, string ShortDescription, string? Image, string Content, int UserId, List<string> Genres) : IRequest<AddResponse>;
+    public record AddRequest(
+        bool MatureContent,
+        [Required][MaxLength(500)] string ShortDescription,
+        [MaxLength(2048)] string? Image,
+        [Required] string Content,
+        int UserId,
+        List<string> Genres
+    ) : IRequest<AddResponse>;
 }
Index: ChapterX.Application/Story/Commands/DeleteHandler.cs
===================================================================
--- ChapterX.Application/Story/Commands/DeleteHandler.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Story/Commands/DeleteHandler.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -22,4 +22,7 @@
                 return new DeleteResponse(false);
 
+            if (story.UserId != request.CallerId)
+                throw new UnauthorizedAccessException("You do not own this story.");
+
             await _storyRepository.DeleteAsync(story, cancellationToken);
 
Index: ChapterX.Application/Story/Commands/DeleteRequest.cs
===================================================================
--- ChapterX.Application/Story/Commands/DeleteRequest.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Story/Commands/DeleteRequest.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -3,4 +3,4 @@
 namespace ChapterX.Application.Story.Commands
 {
-    public record DeleteRequest(int Id) : IRequest<DeleteResponse>;
+    public record DeleteRequest(int Id, int CallerId) : IRequest<DeleteResponse>;
 }
Index: ChapterX.Application/Story/Commands/UpdateHandler.cs
===================================================================
--- ChapterX.Application/Story/Commands/UpdateHandler.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Story/Commands/UpdateHandler.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -22,4 +22,7 @@
                 return new UpdateResponse(false);
 
+            if (story.UserId != request.CallerId)
+                throw new UnauthorizedAccessException("You do not own this story.");
+
             story.MatureContent = request.MatureContent;
             story.ShortDescription = request.ShortDescription;
Index: ChapterX.Application/Story/Commands/UpdateRequest.cs
===================================================================
--- ChapterX.Application/Story/Commands/UpdateRequest.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Application/Story/Commands/UpdateRequest.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -3,4 +3,4 @@
 namespace ChapterX.Application.Story.Commands
 {
-    public record UpdateRequest(int Id, bool MatureContent, string ShortDescription, string? Image, string Content) : IRequest<UpdateResponse>;
+    public record UpdateRequest(int Id, bool MatureContent, string ShortDescription, string? Image, string Content, int CallerId = 0) : IRequest<UpdateResponse>;
 }
Index: ChapterX.Domain/Repositories/IChapterRepository.cs
===================================================================
--- ChapterX.Domain/Repositories/IChapterRepository.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Domain/Repositories/IChapterRepository.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -6,4 +6,5 @@
     {
         Task<IEnumerable<Chapter>> GetByStoryIdAsync(int storyId, CancellationToken cancellationToken = default);
+        Task<Chapter?> GetByIdWithStoryAsync(int id, CancellationToken cancellationToken = default);
     }
 }
Index: apterX.Domain/Shared/PasswordHasher.cs
===================================================================
--- ChapterX.Domain/Shared/PasswordHasher.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ 	(revision )
@@ -1,46 +1,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace ChapterX.Domain.Shared
-{
-    public class PasswordHasher
-    {
-        public static string HashPassword(string password)
-        {
-            byte[] salt;
-            new RNGCryptoServiceProvider().GetBytes(salt = new byte[16]);
-
-            var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000, HashAlgorithmName.SHA256);
-            byte[] hash = pbkdf2.GetBytes(20);
-
-            byte[] hashBytes = new byte[36];
-            Array.Copy(salt, 0, hashBytes, 0, 16);
-            Array.Copy(hash, 0, hashBytes, 16, 20);
-
-            return Convert.ToBase64String(hashBytes);
-        }
-
-        public static bool VerifyPassword(string password, string storedHash)
-        {
-            byte[] hashBytes = Convert.FromBase64String(storedHash);
-            byte[] salt = new byte[16];
-            Array.Copy(hashBytes, 0, salt, 0, 16);
-
-            var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000, HashAlgorithmName.SHA256);
-            byte[] hash = pbkdf2.GetBytes(20);
-
-            for (int i = 0; i < 20; i++)
-            {
-                if (hashBytes[i + 16] != hash[i])
-                {
-                    return false;
-                }
-            }
-            return true;
-        }
-    }
-}
Index: ChapterX.Infrastructure/Repositories/ChapterRepository.cs
===================================================================
--- ChapterX.Infrastructure/Repositories/ChapterRepository.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Infrastructure/Repositories/ChapterRepository.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -24,4 +24,11 @@
                 .ToListAsync(cancellationToken);
         }
+
+        public async Task<Chapter?> GetByIdWithStoryAsync(int id, CancellationToken cancellationToken = default)
+        {
+            return await _dbSet
+                .Include(c => c.Story)
+                .FirstOrDefaultAsync(c => c.Id == id, cancellationToken);
+        }
     }
 }
Index: ChapterX.Infrastructure/Services/JwtTokenService.cs
===================================================================
--- ChapterX.Infrastructure/Services/JwtTokenService.cs	(revision d300631ac3354730c3b03cb7b160974af50e7894)
+++ ChapterX.Infrastructure/Services/JwtTokenService.cs	(revision b373fea3e2c9d404606002f8e7ba265a82d68187)
@@ -23,4 +23,8 @@
             var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
 
+            var role = user.Admin != null ? "Admin"
+                : user.Writer != null ? "Writer"
+                : "RegularUser";
+
             var claims = new[]
             {
@@ -28,5 +32,6 @@
                 new Claim(JwtRegisteredClaimNames.Email, user.Email),
                 new Claim(JwtRegisteredClaimNames.UniqueName, user.Username),
-                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
+                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
+                new Claim(ClaimTypes.Role, role)
             };
 
