diff --git a/src/Managing.Api/Authorization/JwtMiddleware.cs b/src/Managing.Api/Authorization/JwtMiddleware.cs deleted file mode 100644 index 18617e6..0000000 --- a/src/Managing.Api/Authorization/JwtMiddleware.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Managing.Application.Abstractions.Services; - -namespace Managing.Api.Authorization; - -public class JwtMiddleware -{ - private readonly RequestDelegate _next; - - public JwtMiddleware(RequestDelegate next, IConfiguration config) - { - _next = next; - } - - public async Task Invoke(HttpContext context, IUserService userService, IJwtUtils jwtUtils) - { - if (context.Request.Path.StartsWithSegments("/User/create-token") || - context.Request.Path.StartsWithSegments("/swagger") || - context.Request.Path.StartsWithSegments("/health")) - { - await _next(context); - return; - } - - var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last(); - - if (string.IsNullOrEmpty(token)) - { - throw new UnauthorizedAccessException("Authorization token is missing"); - } - - var userId = jwtUtils.ValidateJwtToken(token); - if (userId != null) - { - // attach user to context on successful jwt validation - context.Items["User"] = await userService.GetUserByAddressAsync(userId); - } - - await _next(context); - } -} \ No newline at end of file diff --git a/src/Managing.Api/Controllers/DataController.cs b/src/Managing.Api/Controllers/DataController.cs index 3146c82..07aa3d3 100644 --- a/src/Managing.Api/Controllers/DataController.cs +++ b/src/Managing.Api/Controllers/DataController.cs @@ -554,7 +554,6 @@ public class DataController : ControllerBase } - /// /// Retrieves a paginated list of agent summaries for the agent index page /// @@ -564,6 +563,7 @@ public class DataController : ControllerBase /// Sort order - "asc" or "desc" (defaults to "desc") /// Optional comma-separated list of agent names to filter by /// A paginated list of agent summaries sorted by the specified field + [AllowAnonymous] [HttpGet("GetAgentIndexPaginated")] public async Task> GetAgentIndexPaginated( int page = 1, diff --git a/src/Managing.Api/Program.cs b/src/Managing.Api/Program.cs index 0e323de..ec2079f 100644 --- a/src/Managing.Api/Program.cs +++ b/src/Managing.Api/Program.cs @@ -1,9 +1,11 @@ +using System.Security.Claims; using System.Text; using System.Text.Json.Serialization; using HealthChecks.UI.Client; using Managing.Api.Authorization; using Managing.Api.Filters; using Managing.Api.HealthChecks; +using Managing.Application.Abstractions.Services; using Managing.Application.Hubs; using Managing.Bootstrap; using Managing.Common; @@ -155,20 +157,70 @@ builder.Services.Configure(builder.Configuration.GetSection(Const builder.Services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())); -builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(o => -{ - o.SaveToken = true; - o.TokenValidationParameters = new TokenValidationParameters +builder.Services + .AddAuthentication(options => { - ValidIssuer = builder.Configuration["Authentication:Schemes:Bearer:ValidIssuer"], - ValidAudience = builder.Configuration["Authentication:Schemes:Bearer:ValidAudiences"], - IssuerSigningKey = new SymmetricSecurityKey - (Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Secret"])), - ValidateIssuer = false, - ValidateAudience = false, - ValidateIssuerSigningKey = true - }; -}); + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(o => + { + o.SaveToken = true; + o.TokenValidationParameters = new TokenValidationParameters + { + ValidIssuer = builder.Configuration["Authentication:Schemes:Bearer:ValidIssuer"], + ValidAudience = builder.Configuration["Authentication:Schemes:Bearer:ValidAudiences"], + IssuerSigningKey = new SymmetricSecurityKey + (Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Secret"])), + ValidateIssuer = false, + ValidateAudience = false, + ValidateIssuerSigningKey = true + }; + o.Events = new JwtBearerEvents + { + OnMessageReceived = context => + { + // If you want to get the token from a custom header or query string + // var accessToken = context.Request.Query["access_token"]; + // if (!string.IsNullOrEmpty(accessToken) && + // context.HttpContext.Request.Path.StartsWithSegments("/hub")) + // { + // context.Token = accessToken; + // } + return Task.CompletedTask; + }, + OnAuthenticationFailed = context => + { + if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)) + { + context.Response.Headers.Add("Token-Expired", "true"); + } + + return Task.CompletedTask; + }, + // --- IMPORTANT: Attach User to Context Here --- + OnTokenValidated = async context => + { + var userService = context.HttpContext.RequestServices.GetRequiredService(); + // Assuming your JWT token contains a 'nameid' claim (or similar) for the user ID + var userId = context.Principal.FindFirst(ClaimTypes.NameIdentifier)?.Value; + + if (!string.IsNullOrEmpty(userId)) + { + // Fetch the full user object from your service + var user = await userService.GetUserByAddressAsync(userId); + if (user != null) + { + // Attach the user object to HttpContext.Items + context.HttpContext.Items["User"] = user; + } + } + + await Task.CompletedTask; + } + // --- END IMPORTANT --- + }; + }); builder.Services.AddCors(o => o.AddPolicy("CorsPolicy", builder => { @@ -251,14 +303,9 @@ app.UseSentryDiagnostics(); // Using shared GlobalErrorHandlingMiddleware from core project app.UseMiddleware(); -app.UseMiddleware(); - app.UseHttpsRedirection(); - app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); app.UseEndpoints(endpoints => @@ -280,5 +327,4 @@ app.UseEndpoints(endpoints => }); }); - app.Run(); \ No newline at end of file