source: ChapterX.API/Program.cs@ b373fea

main
Last change on this file since b373fea was b373fea, checked in by kikisrbinoska <srbinoskakristina07@…>, 12 days ago

Fixes for authentication and auhtorization\

  • Property mode set to 100644
File size: 4.5 KB
Line 
1using ChapterX.Application;
2using ChapterX.Infrastructure;
3using Microsoft.AspNetCore.Authentication.JwtBearer;
4using Microsoft.IdentityModel.Tokens;
5using System.Reflection;
6using System.Text;
7
8var builder = WebApplication.CreateBuilder(args);
9
10var jwtKey = builder.Configuration["Jwt:Key"];
11if (string.IsNullOrWhiteSpace(jwtKey) || jwtKey.StartsWith("change-this"))
12 throw new InvalidOperationException("Jwt:Key is not configured. Set it via environment variable DOTNET_Jwt__Key before starting the application.");
13
14builder.Services.AddCors(options =>
15{
16 options.AddPolicy("Frontend", policy =>
17 policy.WithOrigins("http://localhost:5173", "https://localhost:5173")
18 .AllowAnyHeader()
19 .AllowAnyMethod());
20});
21
22builder.Services.AddControllers()
23 .AddJsonOptions(options =>
24 {
25 options.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles;
26 });
27builder.Services.AddEndpointsApiExplorer();
28builder.Services.AddSwaggerGen(options =>
29{
30 options.CustomSchemaIds(type => type.FullName);
31 options.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
32 {
33 Name = "Authorization",
34 Type = Microsoft.OpenApi.Models.SecuritySchemeType.Http,
35 Scheme = "Bearer",
36 BearerFormat = "JWT",
37 In = Microsoft.OpenApi.Models.ParameterLocation.Header,
38 Description = "Enter your JWT token"
39 });
40 options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement
41 {
42 {
43 new Microsoft.OpenApi.Models.OpenApiSecurityScheme
44 {
45 Reference = new Microsoft.OpenApi.Models.OpenApiReference
46 {
47 Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme,
48 Id = "Bearer"
49 }
50 },
51 Array.Empty<string>()
52 }
53 });
54});
55
56builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
57 .AddJwtBearer(options =>
58 {
59 options.TokenValidationParameters = new TokenValidationParameters
60 {
61 ValidateIssuer = true,
62 ValidateAudience = true,
63 ValidateLifetime = true,
64 ValidateIssuerSigningKey = true,
65 ValidIssuer = builder.Configuration["Jwt:Issuer"],
66 ValidAudience = builder.Configuration["Jwt:Audience"],
67 IssuerSigningKey = new SymmetricSecurityKey(
68 Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))
69 };
70 });
71builder.Services.AddAuthorization();
72
73builder.Services.AddApplication();
74builder.Services.AddInfrastructure(builder.Configuration);
75
76var app = builder.Build();
77
78app.UseCors("Frontend");
79
80if (app.Environment.IsDevelopment())
81{
82 app.UseSwagger();
83 app.UseSwaggerUI();
84}
85
86app.UseExceptionHandler(err => err.Run(async ctx =>
87{
88 var ex = ctx.Features.Get<Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature>()?.Error;
89 ctx.Response.ContentType = "application/json";
90
91 var logger = ctx.RequestServices.GetRequiredService<ILogger<Program>>();
92
93 string message;
94 int status;
95
96 if (ex is UnauthorizedAccessException)
97 {
98 status = 401;
99 message = ex.Message;
100 }
101 else if (ex is InvalidOperationException)
102 {
103 status = 400;
104 message = ex.Message;
105 }
106 else if (ex is Microsoft.EntityFrameworkCore.DbUpdateException dbEx)
107 {
108 status = 400;
109 var inner = dbEx.InnerException?.Message ?? "";
110 if (inner.Contains("email_format"))
111 message = "Invalid email format.";
112 else if (inner.Contains("unique") || inner.Contains("duplicate") || inner.Contains("23505"))
113 message = "A user with this email or username already exists.";
114 else
115 {
116 logger.LogError(dbEx, "Unhandled database error");
117 message = "A database error occurred. Please try again.";
118 }
119 }
120 else
121 {
122 logger.LogError(ex, "Unhandled exception");
123 status = 500;
124 message = "An unexpected error occurred.";
125 }
126
127 ctx.Response.StatusCode = status;
128 await ctx.Response.WriteAsJsonAsync(new { message });
129}));
130
131app.UseAuthentication();
132app.UseAuthorization();
133try
134{
135 app.MapControllers();
136}
137catch (ReflectionTypeLoadException ex)
138{
139 Console.Error.WriteLine("ReflectionTypeLoadException while mapping controllers:");
140 foreach (var loaderEx in ex.LoaderExceptions ?? [])
141 {
142 Console.Error.WriteLine(loaderEx.ToString());
143 }
144
145 throw;
146}
147
148app.Run();
Note: See TracBrowser for help on using the repository browser.