Index: backend/Controllers/UsersController.cs
===================================================================
--- backend/Controllers/UsersController.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Controllers/UsersController.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,37 @@
+﻿namespace backend.Controllers;
+
+using backend.Helpers;
+using backend.Models;
+using backend.Services;
+using Microsoft.AspNetCore.Mvc;
+
+[ApiController]
+[Route("[controller]")]
+public class UsersController : ControllerBase
+{
+    private IUserService _userService;
+
+    public UsersController(IUserService userService)
+    {
+        _userService = userService;
+    }
+
+    [HttpPost("authenticate")]
+    public IActionResult Authenticate(AuthenticateRequest model)
+    {
+        var response = _userService.Authenticate(model);
+
+        if (response == null)
+            return BadRequest(new { message = "Username or password is incorrect" });
+
+        return Ok(response);
+    }
+
+    [Authorize]
+    [HttpGet]
+    public IActionResult GetUserById(int id)
+    {
+        var users = _userService.GetById(id);
+        return Ok(users);
+    }
+}
Index: backend/DTOs/AuthenticateRequest.cs
===================================================================
--- backend/DTOs/AuthenticateRequest.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/DTOs/AuthenticateRequest.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,12 @@
+namespace backend.Models;
+
+using System.ComponentModel.DataAnnotations;
+
+public class AuthenticateRequest
+{
+    [Required]
+    public string Username { get; set; }
+
+    [Required]
+    public string Password { get; set; }
+}
Index: backend/DTOs/AuthenticateResponse.cs
===================================================================
--- backend/DTOs/AuthenticateResponse.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/DTOs/AuthenticateResponse.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,19 @@
+using backend.Entities;
+
+namespace backend.Models;
+
+
+public class AuthenticateResponse
+{
+    public int Id { get; set; }
+    public string Username { get; set; }
+    public string Token { get; set; }
+
+
+    public AuthenticateResponse(User user, string token)
+    {
+        Id = user.Id;
+        Username = user.Username;
+        Token = token;
+    }
+}
Index: backend/Data/DataContext.cs
===================================================================
--- backend/Data/DataContext.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Data/DataContext.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,86 @@
+﻿using backend.Entities;
+using Microsoft.EntityFrameworkCore;
+
+namespace backend.Data
+{
+    public class DataContext : DbContext
+    {
+        public DataContext(DbContextOptions<DataContext> dbContextOptions) : base(dbContextOptions)
+        {
+        }
+
+        private DbSet<User> users;
+        public DbSet<User> Users
+        {
+            get
+            {
+                if (users == null)
+                {
+                    users = Set<User>();
+                }
+
+                return users;
+            }
+        }
+
+        private DbSet<Restaurant> restaurants;
+        public DbSet<Restaurant> Restoraunts
+        {
+            get
+            {
+                if (restaurants == null)
+                {
+                    restaurants = Set<Restaurant>();
+                }
+
+                return restaurants;
+            }
+        }
+
+        private DbSet<Reservation> reservations;
+        public DbSet<Reservation> Reservations
+        {
+            get
+            { 
+                if (reservations == null)
+                {
+                    reservations = Set<Reservation>();
+                }
+
+                return reservations;
+            }
+        }
+
+
+        protected override void OnModelCreating(ModelBuilder modelBuilder)
+        {
+            //
+            // User
+            // 
+            modelBuilder.Entity<User>().Property(x => x.Id).IsRequired().ValueGeneratedOnAdd();
+            modelBuilder.Entity<User>()
+            .HasOne(p => p.Restaurant)
+            .WithOne(b => b.Owner);
+
+            //
+            // Restoraunt
+            // 
+            modelBuilder.Entity<Restaurant>().Property(x => x.Id).IsRequired().ValueGeneratedOnAdd();
+            modelBuilder.Entity<Restaurant>()
+            .HasOne(p => p.Owner)
+            .WithOne(b => b.Restaurant)
+            .HasForeignKey<Restaurant>(k => k.OwnerFk);
+            modelBuilder.Entity<Restaurant>()
+            .HasMany(p => p.Reservations)
+            .WithOne(b => b.Restaurant);
+
+            //
+            // Reservation
+            // 
+            modelBuilder.Entity<Reservation>().Property(x => x.Id).IsRequired().ValueGeneratedOnAdd();
+            modelBuilder.Entity<Reservation>()
+            .HasOne(p => p.Restaurant)
+            .WithMany(b => b.Reservations);
+        }
+    }
+}
Index: backend/Entities/Reservation.cs
===================================================================
--- backend/Entities/Reservation.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Entities/Reservation.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,18 @@
+﻿namespace backend.Entities
+{
+    public class Reservation
+    {
+        public int Id { get; set; }
+        public DateTime StartDate { get; set; }
+        public virtual Restaurant Restaurant { get; set; }
+        public ReservationPlace ReservationPlace { get; set; }
+        public ReservationStatus ReservationStatus { get; set; }
+        public ReservationType ReservationType { get; set; }
+        public string ContactName { get; set; }
+        public string ContactNumber { get; set; }
+    }
+
+    public enum ReservationType { Short, Long, Event }
+    public enum ReservationPlace { Outside, Inside}
+    public enum ReservationStatus { New, Confirmed, Cancelled }
+}
Index: backend/Entities/Restaurant.cs
===================================================================
--- backend/Entities/Restaurant.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Entities/Restaurant.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,11 @@
+﻿namespace backend.Entities
+{
+    public class Restaurant
+    {
+        public int Id { get; set; }
+        public int? OwnerFk { get; set; }
+        public virtual User Owner { get; set; }
+        public virtual ICollection<Reservation> Reservations { get; set; }
+        public string Name { get; set; }
+    }
+}
Index: backend/Entities/User.cs
===================================================================
--- backend/Entities/User.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Entities/User.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,9 @@
+namespace backend.Entities;
+
+public class User
+{
+    public int Id { get; set; }
+    public string Username { get; set; }
+    public string Password { get; set; }
+    public virtual Restaurant Restaurant { get; set; }
+}
Index: backend/Helpers/AppSettings.cs
===================================================================
--- backend/Helpers/AppSettings.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Helpers/AppSettings.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,6 @@
+namespace backend.Helpers;
+
+public class AppSettings
+{
+    public string Secret { get; set; }
+}
Index: backend/Helpers/AuthorizeAttribute.cs
===================================================================
--- backend/Helpers/AuthorizeAttribute.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Helpers/AuthorizeAttribute.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,19 @@
+namespace backend.Helpers;
+
+using backend.Entities;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+
+[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
+public class AuthorizeAttribute : Attribute, IAuthorizationFilter
+{
+    public void OnAuthorization(AuthorizationFilterContext context)
+    {
+        var user = (User)context.HttpContext.Items["User"];
+        if (user == null)
+        {
+            // not logged in
+            context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
+        }
+    }
+}
Index: backend/Helpers/JwtMiddleware.cs
===================================================================
--- backend/Helpers/JwtMiddleware.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Helpers/JwtMiddleware.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,56 @@
+namespace WebApi.Helpers;
+
+using Microsoft.Extensions.Options;
+using Microsoft.IdentityModel.Tokens;
+using System.IdentityModel.Tokens.Jwt;
+using System.Text;
+using backend.Services;
+using backend.Helpers;
+
+public class JwtMiddleware
+{
+    private readonly RequestDelegate _next;
+    private readonly AppSettings _appSettings;
+
+    public JwtMiddleware(RequestDelegate next, IOptions<AppSettings> appSettings)
+    {
+        _next = next;
+        _appSettings = appSettings.Value;
+    }
+
+    public async Task Invoke(HttpContext context, IUserService userService)
+    {
+        var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
+
+        if (token != null)
+            attachUserToContext(context, userService, token);
+
+        await _next(context);
+    }
+
+    private void attachUserToContext(HttpContext context, IUserService userService, string token)
+    {
+        try
+        {
+            var tokenHandler = new JwtSecurityTokenHandler();
+            var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
+            tokenHandler.ValidateToken(token, new TokenValidationParameters
+            {
+                ValidateIssuerSigningKey = true,
+                IssuerSigningKey = new SymmetricSecurityKey(key),
+                ValidateIssuer = false,
+                ValidateAudience = false,
+                ClockSkew = TimeSpan.Zero
+            }, out SecurityToken validatedToken);
+
+            var jwtToken = (JwtSecurityToken)validatedToken;
+            var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value);
+
+            context.Items["User"] = userService.GetById(userId);
+        }
+        catch
+        {
+            // do nothing if jwt validation fails
+        }
+    }
+}
Index: backend/Migrations/20220409103618_Initial-Architecture.Designer.cs
===================================================================
--- backend/Migrations/20220409103618_Initial-Architecture.Designer.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Migrations/20220409103618_Initial-Architecture.Designer.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,142 @@
+﻿// <auto-generated />
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using backend.Data;
+
+#nullable disable
+
+namespace backend.Migrations
+{
+    [DbContext(typeof(DataContext))]
+    [Migration("20220409103618_Initial-Architecture")]
+    partial class InitialArchitecture
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "6.0.3")
+                .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+            NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+            modelBuilder.Entity("backend.Entities.Reservation", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer");
+
+                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
+
+                    b.Property<string>("ContactName")
+                        .IsRequired()
+                        .HasColumnType("text");
+
+                    b.Property<string>("ContactNumber")
+                        .IsRequired()
+                        .HasColumnType("text");
+
+                    b.Property<int>("ReservationPlace")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("ReservationStatus")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("ReservationType")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("RestaurantId")
+                        .HasColumnType("integer");
+
+                    b.Property<DateTime>("StartDate")
+                        .HasColumnType("timestamp with time zone");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("RestaurantId");
+
+                    b.ToTable("Reservations");
+                });
+
+            modelBuilder.Entity("backend.Entities.Restaurant", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer");
+
+                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("text");
+
+                    b.Property<int?>("OwnerFk")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OwnerFk")
+                        .IsUnique();
+
+                    b.ToTable("Restoraunts");
+                });
+
+            modelBuilder.Entity("backend.Entities.User", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer");
+
+                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasColumnType("text");
+
+                    b.Property<string>("Username")
+                        .IsRequired()
+                        .HasColumnType("text");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Users");
+                });
+
+            modelBuilder.Entity("backend.Entities.Reservation", b =>
+                {
+                    b.HasOne("backend.Entities.Restaurant", "Restaurant")
+                        .WithMany("Reservations")
+                        .HasForeignKey("RestaurantId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Restaurant");
+                });
+
+            modelBuilder.Entity("backend.Entities.Restaurant", b =>
+                {
+                    b.HasOne("backend.Entities.User", "Owner")
+                        .WithOne("Restaurant")
+                        .HasForeignKey("backend.Entities.Restaurant", "OwnerFk");
+
+                    b.Navigation("Owner");
+                });
+
+            modelBuilder.Entity("backend.Entities.Restaurant", b =>
+                {
+                    b.Navigation("Reservations");
+                });
+
+            modelBuilder.Entity("backend.Entities.User", b =>
+                {
+                    b.Navigation("Restaurant")
+                        .IsRequired();
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
Index: backend/Migrations/20220409103618_Initial-Architecture.cs
===================================================================
--- backend/Migrations/20220409103618_Initial-Architecture.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Migrations/20220409103618_Initial-Architecture.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,95 @@
+﻿using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace backend.Migrations
+{
+    public partial class InitialArchitecture : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.CreateTable(
+                name: "Users",
+                columns: table => new
+                {
+                    Id = table.Column<int>(type: "integer", nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+                    Username = table.Column<string>(type: "text", nullable: false),
+                    Password = table.Column<string>(type: "text", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Users", x => x.Id);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Restoraunts",
+                columns: table => new
+                {
+                    Id = table.Column<int>(type: "integer", nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+                    OwnerFk = table.Column<int>(type: "integer", nullable: true),
+                    Name = table.Column<string>(type: "text", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Restoraunts", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Restoraunts_Users_OwnerFk",
+                        column: x => x.OwnerFk,
+                        principalTable: "Users",
+                        principalColumn: "Id");
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Reservations",
+                columns: table => new
+                {
+                    Id = table.Column<int>(type: "integer", nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+                    StartDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
+                    RestaurantId = table.Column<int>(type: "integer", nullable: false),
+                    ReservationPlace = table.Column<int>(type: "integer", nullable: false),
+                    ReservationStatus = table.Column<int>(type: "integer", nullable: false),
+                    ReservationType = table.Column<int>(type: "integer", nullable: false),
+                    ContactName = table.Column<string>(type: "text", nullable: false),
+                    ContactNumber = table.Column<string>(type: "text", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Reservations", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Reservations_Restoraunts_RestaurantId",
+                        column: x => x.RestaurantId,
+                        principalTable: "Restoraunts",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Reservations_RestaurantId",
+                table: "Reservations",
+                column: "RestaurantId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Restoraunts_OwnerFk",
+                table: "Restoraunts",
+                column: "OwnerFk",
+                unique: true);
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropTable(
+                name: "Reservations");
+
+            migrationBuilder.DropTable(
+                name: "Restoraunts");
+
+            migrationBuilder.DropTable(
+                name: "Users");
+        }
+    }
+}
Index: backend/Migrations/DataContextModelSnapshot.cs
===================================================================
--- backend/Migrations/DataContextModelSnapshot.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Migrations/DataContextModelSnapshot.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,140 @@
+﻿// <auto-generated />
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using backend.Data;
+
+#nullable disable
+
+namespace backend.Migrations
+{
+    [DbContext(typeof(DataContext))]
+    partial class DataContextModelSnapshot : ModelSnapshot
+    {
+        protected override void BuildModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "6.0.3")
+                .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+            NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+            modelBuilder.Entity("backend.Entities.Reservation", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer");
+
+                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
+
+                    b.Property<string>("ContactName")
+                        .IsRequired()
+                        .HasColumnType("text");
+
+                    b.Property<string>("ContactNumber")
+                        .IsRequired()
+                        .HasColumnType("text");
+
+                    b.Property<int>("ReservationPlace")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("ReservationStatus")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("ReservationType")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("RestaurantId")
+                        .HasColumnType("integer");
+
+                    b.Property<DateTime>("StartDate")
+                        .HasColumnType("timestamp with time zone");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("RestaurantId");
+
+                    b.ToTable("Reservations");
+                });
+
+            modelBuilder.Entity("backend.Entities.Restaurant", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer");
+
+                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("text");
+
+                    b.Property<int?>("OwnerFk")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OwnerFk")
+                        .IsUnique();
+
+                    b.ToTable("Restoraunts");
+                });
+
+            modelBuilder.Entity("backend.Entities.User", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer");
+
+                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasColumnType("text");
+
+                    b.Property<string>("Username")
+                        .IsRequired()
+                        .HasColumnType("text");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Users");
+                });
+
+            modelBuilder.Entity("backend.Entities.Reservation", b =>
+                {
+                    b.HasOne("backend.Entities.Restaurant", "Restaurant")
+                        .WithMany("Reservations")
+                        .HasForeignKey("RestaurantId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Restaurant");
+                });
+
+            modelBuilder.Entity("backend.Entities.Restaurant", b =>
+                {
+                    b.HasOne("backend.Entities.User", "Owner")
+                        .WithOne("Restaurant")
+                        .HasForeignKey("backend.Entities.Restaurant", "OwnerFk");
+
+                    b.Navigation("Owner");
+                });
+
+            modelBuilder.Entity("backend.Entities.Restaurant", b =>
+                {
+                    b.Navigation("Reservations");
+                });
+
+            modelBuilder.Entity("backend.Entities.User", b =>
+                {
+                    b.Navigation("Restaurant")
+                        .IsRequired();
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
Index: backend/Program.cs
===================================================================
--- backend/Program.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Program.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,73 @@
+using backend.Data;
+using backend.Helpers;
+using backend.Services;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.Swagger;
+using WebApi.Helpers;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Add services to the container.
+builder.Services.Configure<AppSettings>(builder.Configuration.GetSection("AppSettings"));
+builder.Services.AddControllers();
+// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
+builder.Services.AddEndpointsApiExplorer();
+builder.Services.AddSwaggerGen(c =>
+{
+    c.SwaggerDoc("v1", new OpenApiInfo() { Title = "resTools backend", Version = "v1" });
+    c.AddSecurityDefinition("Bearer",
+        new OpenApiSecurityScheme
+        {
+            In = Microsoft.OpenApi.Models.ParameterLocation.Header,
+            Description = "Please enter into field the word 'Bearer' following by space and JWT",
+            Name = "Authorization",
+            Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey,
+            Scheme="Bearer"
+        });
+    c.AddSecurityRequirement(new OpenApiSecurityRequirement()
+    {
+        {
+            new OpenApiSecurityScheme
+            {
+                Reference = new OpenApiReference
+                {
+                    Type = ReferenceType.SecurityScheme,
+                    Id = "Bearer"
+                },
+                Name = "Bearer",
+                In = ParameterLocation.Header,
+
+            },
+            new List<string>()
+        }
+    });
+});
+builder.Services.AddScoped<IUserService, UserService>();
+
+builder.Services.AddDbContext<DataContext>(p => p.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
+
+var app = builder.Build();
+
+app.UseCors(x => x
+        .AllowAnyOrigin()
+        .AllowAnyMethod()
+        .AllowAnyHeader());
+
+// custom jwt auth middleware
+app.UseMiddleware<JwtMiddleware>();
+
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment())
+{
+    app.UseSwagger();
+    app.UseSwaggerUI();
+}
+
+app.UseHttpsRedirection();
+
+app.UseAuthorization();
+
+app.MapControllers();
+
+app.Run();
Index: backend/Properties/launchSettings.json
===================================================================
--- backend/Properties/launchSettings.json	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Properties/launchSettings.json	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,31 @@
+﻿{
+  "$schema": "https://json.schemastore.org/launchsettings.json",
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:16765",
+      "sslPort": 44324
+    }
+  },
+  "profiles": {
+    "backend": {
+      "commandName": "Project",
+      "dotnetRunMessages": true,
+      "launchBrowser": true,
+      "launchUrl": "swagger",
+      "applicationUrl": "https://localhost:7073;http://localhost:5073",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "launchUrl": "swagger",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}
Index: backend/Services/UserService.cs
===================================================================
--- backend/Services/UserService.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/Services/UserService.cs	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,65 @@
+namespace backend.Services;
+
+using backend.Entities;
+using backend.Helpers;
+using backend.Models;
+using Microsoft.Extensions.Options;
+using Microsoft.IdentityModel.Tokens;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+using System.Text;
+
+public interface IUserService
+{
+    AuthenticateResponse Authenticate(AuthenticateRequest model);
+    User GetById(int id);
+}
+
+public class UserService : IUserService
+{
+    // users hardcoded for simplicity, store in a db with hashed passwords in production applications
+    private List<User> _users = new List<User>
+    {
+        new User { Id = 1, Username = "test", Password = "test" }
+    };
+
+    private readonly AppSettings _appSettings;
+
+    public UserService(IOptions<AppSettings> appSettings)
+    {
+        _appSettings = appSettings.Value;
+    }
+
+    public AuthenticateResponse Authenticate(AuthenticateRequest model)
+    {
+        var user = _users.SingleOrDefault(x => x.Username == model.Username && x.Password == model.Password);
+
+        // return null if user not found
+        if (user == null) return null;
+
+        // authentication successful so generate jwt token
+        var token = generateJwtToken(user);
+
+        return new AuthenticateResponse(user, token);
+    }
+
+    public User GetById(int id)
+    {
+        return _users.FirstOrDefault(x => x.Id == id);
+    }
+
+    private string generateJwtToken(User user)
+    {
+        // generate token that is valid for 7 days
+        var tokenHandler = new JwtSecurityTokenHandler();
+        var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
+        var tokenDescriptor = new SecurityTokenDescriptor
+        {
+            Subject = new ClaimsIdentity(new[] { new Claim("id", user.Id.ToString()) }),
+            Expires = DateTime.UtcNow.AddDays(7),
+            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
+        };
+        var token = tokenHandler.CreateToken(tokenDescriptor);
+        return tokenHandler.WriteToken(token);
+    }
+}
Index: backend/appsettings.Development.json
===================================================================
--- backend/appsettings.Development.json	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/appsettings.Development.json	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,8 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  }
+}
Index: backend/appsettings.json
===================================================================
--- backend/appsettings.json	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/appsettings.json	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,15 @@
+{
+  "AppSettings": {
+    "Secret": "chWS2ewNYT2tpLWIm1L5ty12c8FINao7p65LxPPM7GjkytlI5X1iZYWuh5KQhZgxkQqf8FVZuklWTfp0fDd4pvFy8ND6ecgircfxG2IckDzte1I2ZrTMS7xhpsux8vLxLGkGUi9ZXOAO9oaOYP5IelwJdiHiryEj9BdfMGT1QgRfsHHazqz6gtrJIcdW2pb3yrXPGtQ20UvXgXxw7dyAwd3byZexM0t781qgp7rT71YgkVyc8YBx74U6DcWtSka7"
+  },
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  },
+  "ConnectionStrings": {
+    "DefaultConnection": "Server=localhost; port=5432; user id = postgres; database=resToolsDB; password=121212; pooling = true; includeerrordetail = true"
+  },
+  "AllowedHosts": "*"
+}
Index: backend/backend.csproj
===================================================================
--- backend/backend.csproj	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
+++ backend/backend.csproj	(revision b66b3acb77c10d451916af5571fc0b31168ad254)
@@ -0,0 +1,24 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <Nullable>enable</Nullable>
+    <ImplicitUsings>enable</ImplicitUsings>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.3" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.3" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.3">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
+    <PackageReference Include="Npgsql" Version="6.0.3" />
+    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.3" />
+    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
+    <PackageReference Include="Swashbuckle.Core" Version="5.6.0" />
+    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.17.0" />
+  </ItemGroup>
+
+</Project>
