skip to Main Content

I’m working on integrating Identity into my .NET Core 8.0 application and implementing JWT Bearer authentication. However, I’m encountering the error

System.InvalidOperationException: Scheme already exists: Bearer

when running the application.

My Program.cs code is :

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();

I have tried rearranging the order of middleware and authentication setup in Program.cs, but the error persists.

I have checked for duplicate calls to AddAuthentication and AddJwtBearer methods.

If needed, I can provide a simplified version of my code focusing on the authentication setup that causes the error.

Environment

  • .NET Core 8.0
  • Identity framework version 8.0.0
  • Visual Studio 2022
  • Windows 10

2

Answers


  1. This would fix the problem:

    .AddJwtBearer("GiveSomeUniqueNameHere", options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                    {
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.PrivateKey)),
                        ValidateIssuer = false,
                        ValidateAudience = false
                    };
            });
    

    This is how you would specify a name for the authentication scheme, thereby avoiding conflicting default-named schemes. See https://learn.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-8.0

    Additional authentication has to be registered with a unique
    authentication scheme.

    However, you probably should look into where that other scheme was coming from and get rid of it if you don’t need it.

    I see that you are adding some KeyCloak related stuff, maybe try commenting those out to see if the problem goes away. These methods are most likely adding some authentication schemes to the project.

    P.S. Unrelated, but what’s the builder.Services.AddExceptionHandler<ExceptionHandler>(); for? You can use the built-in UseExceptionHandler for global exception handling, unless you really needed something custom.

    Login or Signup to reply.
  2. The default value for JwtBearerDefaults.AuthenticationScheme is Bearer (see sources)

    You set this as the scheme here:

    builder.Services.AddAuthentication(x =>
    {
        x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    

    The naming-conflict stems from using the following code with the default schema (which is also Bearer):

    .AddJwtBearer(x =>
    {
        x.TokenValidationParameters = new TokenValidationParameters
        {
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.PrivateKey)),
            ValidateIssuer = false,
            ValidateAudience = false
        };
    })
    

    To avoid this, you can either use a different schema when calling AddAuthentication or use a different schema when calling AddJwtBearer. For example:

    .AddJwtBearer("mySchema", x =>
    {
        x.TokenValidationParameters = new TokenValidationParameters
        {
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.PrivateKey)),
            ValidateIssuer = false,
            ValidateAudience = false
        };
    })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search