My Mobile API is currently using IdentityServer and for various reasons I need to replace it with something far simpler such as JWTs. I have a service with some very basic JWT issuing and validating etc based on the current standards etc however I'm having trouble plugging it into my current .NET 6 Web API.

My TokenService pseudo-code

public class TokenService : ITokenService
{
    public string GetJwt();
    public JwtSecurityToken DecodeJwt();
}

My Starup.cs file currently looks something like this which has been working nicely for years. This method is called within ConfigureServices:

private void ConfigureIdentityServer(IServiceCollection services)
{
    services.AddAuthentication("Bearer")
        // Add the IdentityServer access token validation handler into DI for use by the authentication services.
       .AddIdentityServerAuthentication(options =>
       {
           options.Authority = Config.IdentityServerBaseUri;
           options.RequireHttpsMetadata = false;
           options.ApiName = Config.AppApiName;
           options.ApiSecret = Config.ClientSecret;
       });
}

And my AccountController is something like this:

[HttpGet]
[Authorize]
[CustomClaimFilter]        
public IActionResult Get()
{
    // Get the claims and return the user account details
}

What I want to be able to do with my new JWT stuff is essentially have the user authenticated with the API using either the IdentityServer OR the JWT based on a header supplied by the requesting client for example auth-method: jwt etc.

I'm guessing that there are two main changes I need to make in order to get this to work. Firstly something along the lines of AddJwtBearer within the ConfigureIdentityServer method shown above but also some code to somehow switch between the two based on the header.

I'm having difficulty figuring out the AddJwtBearer stuff and I've no idea where to start with the switching!

Any advice is appreciated, thanks.

1

There are 1 best solutions below

1
Fengzhi Zhou On

You can add a switch with header in your request

Program.cs

using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

builder.Services.AddAuthentication(options =>
{
    // Set the default scheme to IdentityServer or JWT
    options.DefaultAuthenticateScheme = "JwtBearer";
    options.DefaultScheme = "JwtBearer";
    options.DefaultChallengeScheme = "JwtBearer";
})
        .AddJwtBearer("JwtBearer", options =>
        {
            // Configure JWT Bearer options, such as:
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = "https://localhost:7219",
                ValidAudience = "https://localhost:7219",
                IssuerSigningKey = new SymmetricSecurityKey(
                    Encoding.UTF8.GetBytes("my_too_strong_access_secret_key_longer"))
            };
        })
        .AddIdentityServerAuthentication("IdentityServer", options =>
        {
            // Your existing IdentityServer configuration
        });

builder.Services.AddAuthorization();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.Use(async (context, next) =>
{
    var authMethod = context.Request.Headers["auth-method"].FirstOrDefault();

    if (!string.IsNullOrEmpty(authMethod))
    {
        // Dynamically set the authentication scheme based on the "auth-method" header
        var scheme = authMethod.Equals("jwt", StringComparison.OrdinalIgnoreCase)
            ? "JwtBearer" // The name of the JWT Bearer scheme you configured
            : "IdentityServer"; // The name of the IdentityServer authentication scheme

        context.Request.Headers["Authorization"] = new Microsoft.Extensions.Primitives.StringValues($"{scheme} {context.Request.Headers["Authorization"].FirstOrDefault()}");
    }

    // Continue on to the next middleware
    await next.Invoke();
});

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Then in your [authorize] endpoint with token passed, add the header of JwtBearer/IdentityServer, it will authorize with your selected way.

enter image description here