Я работаю над интеграцией Identity в свое приложение .NET Core 8.0 и реализацией аутентификации носителя JWT. Однако я сталкиваюсь с ошибкой
System.InvalidOperationException: схема уже существует: носитель
при запуске приложения.
Мой код Program.cs:
using Solv.Identity.Api.Common;
using Solv.Identity.Api.Configurations;
using Solv.Identity.Api.Endpoints;
using Solv.Identity.Infrastructure;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Solv.Identity.Application.Auth;
using Solv.Identity.Application.Features.Configuration;
using System.Text;
using Solv.Identity.Application.Features.Users;
using System;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
var builder = WebApplication.CreateBuilder(args);
// Register AuthService
builder.Services.AddTransient<AuthService>();
// Add authentication and authorization
builder.Services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.PrivateKey)),
ValidateIssuer = false,
ValidateAudience = false
};
});
builder.Services.AddAuthorization(x =>
{
x.AddPolicy("tech", p => p.RequireRole("developer"));
});
// Controllers
builder.AddValidationSetup();
// Swagger
builder.Services.AddSwaggerSetup();
// Persistence
builder.Services.AddPersistenceSetup(builder.Configuration);
// Application layer setup
builder.Services.AddApplicationSetup();
// Request response compression
builder.Services.AddCompressionSetup();
//// HttpContextAcessor
builder.Services.AddHttpContextAccessor();
//// Mediator
builder.Services.AddMediatRSetup();
//// Exception handler
builder.Services.AddExceptionHandler<ExceptionHandler>();
builder.Logging.ClearProviders();
// Add serilog
if (builder.Environment.EnvironmentName != "Testing")
{
//builder.Host.UseLoggingSetup(builder.Configuration);
// Add opentelemetry
builder.AddOpenTemeletrySetup();
}
builder.Services.AddHttpClient();
#region Keycloak
builder.Services.AddKeycloakServices();
builder.AddKeycloakSettings();
builder.AddKeycloakAuthorization();
#endregion
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseResponseCompression();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseSwaggerSetup();
app.UseHsts();
app.UseResponseCompression();
app.UseHttpsRedirection();
// Configure middleware
app.UseAuthentication();
app.UseAuthorization();
// Define endpoints
app.MapGet("/login", (AuthService service) =>
{
var user = new User(
1,
"M.Sohail",
"M.Sohail",
"[email protected]",
"abcd123",
new[] { "developer" });
return service.Create(user);
});
app.MapGet("/test", () => "OK!")
.RequireAuthorization();
app.MapGet("/test/tech", () => "tech OK!")
.RequireAuthorization("tech");
app.UseMiddleware<LoggingMiddleware>();
await app.Migrate();
await app.RunAsync();
Я попытался изменить порядок установки промежуточного программного обеспечения и аутентификации в Program.cs, но ошибка не устранена.
Я проверил дублирование вызовов методов AddAuthentication и AddJwtBearer.
При необходимости я могу предоставить упрощенную версию своего кода с упором на настройку аутентификации, которая вызывает ошибку.
Среда





Это решит проблему:
.AddJwtBearer("GiveSomeUniqueNameHere", options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.PrivateKey)),
ValidateIssuer = false,
ValidateAudience = false
};
});
Именно так вы можете указать имя для схемы аутентификации, избегая тем самым конфликта схем с именами по умолчанию. См. https://learn.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-8.0
Дополнительную аутентификацию необходимо зарегистрировать с помощью уникального схема аутентификации.
Однако вам, вероятно, следует выяснить, откуда взялась эта другая схема, и избавиться от нее, если она вам не нужна.
Я вижу, что вы добавляете некоторые вещи, связанные с KeyCloak, возможно, попробуйте прокомментировать их, чтобы посмотреть, исчезнет ли проблема. Эти методы, скорее всего, добавляют в проект какие-то схемы аутентификации.
P.S. Не имеет отношения к делу, но для чего нужен builder.Services.AddExceptionHandler<ExceptionHandler>();? Вы можете использовать встроенный UseExceptionHandler для глобальной обработки исключений, если только вам действительно не нужно что-то особенное.
Значение по умолчанию для JwtBearerDefaults.AuthenticationScheme — Bearer (см. источники )
Вы устанавливаете это как схему здесь:
builder.Services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
Конфликт имен возникает из-за использования следующего кода со схемой по умолчанию (которая также Bearer):
.AddJwtBearer(x =>
{
x.TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.PrivateKey)),
ValidateIssuer = false,
ValidateAudience = false
};
})
Чтобы избежать этого, вы можете использовать другую схему при вызове AddAuthentication или использовать другую схему при вызове AddJwtBearer. Например:
.AddJwtBearer("mySchema", x =>
{
x.TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.PrivateKey)),
ValidateIssuer = false,
ValidateAudience = false
};
})
Сообщение об ошибке понятно: вы зарегистрировали более одной схемы Bearer. Поскольку я не могу воспроизвести ваш проект, вы можете прокомментировать потенциальное промежуточное программное обеспечение, в котором может быть зарегистрирована схема, чтобы выяснить причину.