using System.Text; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using SPMS.Application.Interfaces; using SPMS.Application.Settings; namespace SPMS.API.Extensions; public static class AuthenticationExtensions { public static IServiceCollection AddJwtAuthentication( this IServiceCollection services, IConfiguration configuration) { var jwtSettings = configuration.GetSection(JwtSettings.SectionName).Get()!; services.Configure(configuration.GetSection(JwtSettings.SectionName)); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = jwtSettings.Issuer, ValidAudience = jwtSettings.Audience, IssuerSigningKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(jwtSettings.SecretKey)), ClockSkew = TimeSpan.Zero }; options.Events = new JwtBearerEvents { OnTokenValidated = async context => { var tokenStore = context.HttpContext.RequestServices .GetRequiredService(); var jti = context.Principal?.FindFirst("jti")?.Value; if (!string.IsNullOrEmpty(jti)) { var blacklisted = await tokenStore.GetAsync($"blacklist:{jti}"); if (blacklisted != null) context.Fail("토큰이 무효화되었습니다."); } } }; }); return services; } public static IServiceCollection AddAuthorizationPolicies(this IServiceCollection services) { services.AddAuthorization(options => { options.AddPolicy("SuperOnly", policy => policy.RequireRole("Super")); options.AddPolicy("ManagerOrAbove", policy => policy.RequireRole("Super", "Manager")); }); return services; } }