#384 Авторизации + получение id пользователя в контроллерах #3

Merged
on.nemtina merged 7 commits from PersistenceClient into master 2024-11-25 17:09:22 +05:00
3 changed files with 103 additions and 82 deletions
Showing only changes of commit b79d29f08e - Show all commits

View File

@ -1,14 +1,10 @@
using System.Text.Json.Nodes;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using Persistence.Models;
using Persistence.Models.Configurations; using Persistence.Models.Configurations;
using System.Data.Common; using Swashbuckle.AspNetCore.SwaggerGen;
using System.Text;
using System.Text.Json.Nodes;
namespace Persistence.API; namespace Persistence.API;
@ -39,95 +35,46 @@ public static class DependencyInjection
var needUseKeyCloak = configuration.GetSection("NeedUseKeyCloak").Get<bool>(); var needUseKeyCloak = configuration.GetSection("NeedUseKeyCloak").Get<bool>();
if (needUseKeyCloak) if (needUseKeyCloak)
{ c.AddKeycloackSecurity(configuration);
c.AddSecurityDefinition("Keycloack", new OpenApiSecurityScheme else c.AddDefaultSecurity(configuration);
{
Description = @"JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below. Example: 'Bearer 12345abcdef'",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
Implicit = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri(configuration["Authentication:AuthorizationUrl"]),
}
}
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Keycloack"
},
Scheme = "Bearer",
Name = "Bearer",
In = ParameterLocation.Header,
},
new List<string>()
}
});
}
else
{
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = @"JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below. Example: 'Bearer 12345abcdef'",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header,
},
new List<string>()
}
});
}
//var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; //var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
Review

Блок кода с if-else c настройками аутентификации для сваггера желательно убрать в отдельный метод

Блок кода с if-else c настройками аутентификации для сваггера желательно убрать в отдельный метод
//var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); //var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
//var includeControllerXmlComment = true; //var includeControllerXmlComment = true;
//c.IncludeXmlComments(xmlPath, includeControllerXmlComment); //options.IncludeXmlComments(xmlPath, includeControllerXmlComment);
//c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "AsbCloudApp.xml"), includeControllerXmlComment); //options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "AsbCloudApp.xml"), includeControllerXmlComment);
}); });
} }
public static void AddJWTAuthentication(this IServiceCollection services, IConfiguration configuration) #region Authentication
public static void AddJWTAuthentication(this IServiceCollection services, IConfiguration configuration)
{ {
var needUseKeyCloak = configuration var needUseKeyCloak = configuration
.GetSection("NeedUseKeyCloak") .GetSection("NeedUseKeyCloak")
.Get<bool>(); .Get<bool>();
if (needUseKeyCloak) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) if (needUseKeyCloak)
services.AddKeyCloakAuthentication(configuration);
else services.AddDefaultAuthentication(configuration);
}
private static void AddKeyCloakAuthentication(this IServiceCollection services, IConfiguration configuration)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => .AddJwtBearer(options =>
{ {
options.RequireHttpsMetadata = false; options.RequireHttpsMetadata = false;
options.Audience = configuration["Authentication:Audience"]; options.Audience = configuration["Authentication:Audience"];
options.MetadataAddress = configuration["Authentication:MetadataAddress"]!; options.MetadataAddress = configuration["Authentication:MetadataAddress"]!;
options.TokenValidationParameters = new TokenValidationParameters options.TokenValidationParameters = new TokenValidationParameters
{ {
ValidIssuer = configuration["Authentication:ValidIssuer"], ValidIssuer = configuration["Authentication:ValidIssuer"],
}; };
}); });
else services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) }
private static void AddDefaultAuthentication(this IServiceCollection services, IConfiguration configuration)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => .AddJwtBearer(options =>
{ {
options.RequireHttpsMetadata = false; options.RequireHttpsMetadata = false;
@ -176,4 +123,73 @@ public static class DependencyInjection
}; };
}); });
} }
#endregion
#region Security (Swagger)
private static void AddKeycloackSecurity(this SwaggerGenOptions options, IConfiguration configuration)
{
options.AddSecurityDefinition("Keycloack", new OpenApiSecurityScheme
{
Description = @"JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below. Example: 'Bearer 12345abcdef'",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
Implicit = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri(configuration["Authentication:AuthorizationUrl"]),
}
}
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Keycloack"
},
Scheme = "Bearer",
Name = "Bearer",
In = ParameterLocation.Header,
},
new List<string>()
}
});
}
private static void AddDefaultSecurity(this SwaggerGenOptions options, IConfiguration configuration)
{
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = @"JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below. Example: 'Bearer 12345abcdef'",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header,
},
new List<string>()
}
});
}
#endregion
} }

View File

@ -1,11 +1,13 @@
using System.Text.Json; using System.Text.Json;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Persistence.Client.Helpers; using Persistence.Client.Helpers;
using Persistence.Models.Configurations;
using Refit; using Refit;
namespace Persistence.Client namespace Persistence.Client
{ {
/// <summary>
/// Фабрика клиентов для доступа к Persistence - сервису

Желательно добавить комментарий к этим 2-м фабрикам: к PersistenceClientFactory и TestHttpClientFactory

Желательно добавить комментарий к этим 2-м фабрикам: к PersistenceClientFactory и TestHttpClientFactory
/// </summary>
public class PersistenceClientFactory public class PersistenceClientFactory
{ {
private static readonly JsonSerializerOptions JsonSerializerOptions = new() private static readonly JsonSerializerOptions JsonSerializerOptions = new()

View File

@ -1,5 +1,8 @@
namespace Persistence.IntegrationTests namespace Persistence.IntegrationTests
{ {
/// <summary>
/// Фабрика HTTP клиентов для интеграционных тестов
/// </summary>
public class TestHttpClientFactory : IHttpClientFactory public class TestHttpClientFactory : IHttpClientFactory
{ {
private readonly WebAppFactoryFixture factory; private readonly WebAppFactoryFixture factory;