using System.IdentityModel.Tokens.Jwt; using System.Reflection; using System.Text; using FluentValidation; using FluentValidation.AspNetCore; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; using WatchIt.Database; using WatchIt.WebAPI.Services.Controllers.Accounts; using WatchIt.WebAPI.Services.Controllers.Genres; using WatchIt.WebAPI.Services.Controllers.Media; using WatchIt.WebAPI.Services.Controllers.Movies; using WatchIt.WebAPI.Services.Controllers.Series; using WatchIt.WebAPI.Services.Utility.Configuration; using WatchIt.WebAPI.Services.Utility.Tokens; using WatchIt.WebAPI.Services.Utility.User; using WatchIt.WebAPI.Validators; using WatchIt.WebAPI.WorkerServices; namespace WatchIt.WebAPI; public static class Program { #region PUBLIC METHODS public static void Main(string[] args) { WebApplication app = WebApplication.CreateBuilder(args) .SetupAuthentication() .SetupDatabase() .SetupWorkerServices() .SetupServices() .SetupApplication() .Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run(); } #endregion #region PRIVATE METHODS private static WebApplicationBuilder SetupAuthentication(this WebApplicationBuilder builder) { JsonWebTokenHandler.DefaultInboundClaimTypeMap.Clear(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); AuthenticationBuilder authenticationBuilder = builder.Services.AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }); authenticationBuilder.AddJwtBearer(x => { x.RequireHttpsMetadata = false; x.SaveToken = true; x.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration.GetValue("Authentication:Key")!)), ValidateAudience = true, ValidAudience = "access", ValidIssuer = builder.Configuration.GetValue("Authentication:Issuer"), ValidateLifetime = true, ClockSkew = TimeSpan.FromMinutes(1), }; x.Events = new JwtBearerEvents { OnAuthenticationFailed = context => { if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)) { context.Response.Headers.Append("Token-Expired", "true"); } return Task.CompletedTask; }, }; }); authenticationBuilder.AddJwtBearer("refresh", x => { x.RequireHttpsMetadata = false; x.SaveToken = true; x.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration.GetValue("Authentication:Key")!)), ValidateAudience = true, ValidIssuer = builder.Configuration.GetValue("Authentication:Issuer"), ValidAudience = "refresh", ValidateLifetime = true, ClockSkew = TimeSpan.FromMinutes(1) }; x.Events = new JwtBearerEvents { OnAuthenticationFailed = context => { if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)) { context.Response.Headers.Append("Token-Expired", "true"); } return Task.CompletedTask; } }; }); builder.Services.AddAuthorization(); return builder; } private static WebApplicationBuilder SetupDatabase(this WebApplicationBuilder builder) { builder.Services.AddDbContext(x => x.UseLazyLoadingProxies().UseNpgsql(builder.Configuration.GetConnectionString("Default")), ServiceLifetime.Transient); return builder; } private static WebApplicationBuilder SetupWorkerServices(this WebApplicationBuilder builder) { builder.Services.AddHostedService(); return builder; } private static WebApplicationBuilder SetupServices(this WebApplicationBuilder builder) { // Utility builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); // Controller builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); return builder; } private static WebApplicationBuilder SetupApplication(this WebApplicationBuilder builder) { builder.Services.AddValidatorsFromAssembly(Assembly.GetAssembly(typeof(CustomValidators))); builder.Services.AddFluentValidationAutoValidation(); builder.Services.AddHttpContextAccessor(); builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); return builder; } #endregion }