0

I created an web api project with built in authentication (when I created it I checked the "with authentication" box) and now I want to make it more secure. Is there a way to integrate the jwt authentication with the already existing authentication created by the project? I added this in ConfigureServices method from Startup.cs:

services.AddAuthentication()
        .AddIdentityServerJwt();

I am very new to asp.net and jwt and I find it very hard to understand the processes.

Deeriss
  • 23
  • 1
  • 5

1 Answers1

0

define multiple auth Method like this:

builder.Services.AddAuthentication(opt =>
{
//default config
opt.DefaultScheme = "UNKNOWN";
opt.DefaultChallengeScheme = "UNKNOWN";
})
.AddJwtBearer("keycloak", options =>
{
// first auth method (validate keycloak token with publicKey)
    options.RequireHttpsMetadata = false;

    var publicKey = new ReadOnlySpan<byte>(Convert.FromBase64String(builder.Configuration["KeycloakJwtAuth:key"]));
    var rsa = RSA.Create();
    int readByte = 0;
    rsa.ImportSubjectPublicKeyInfo(publicKey, out readByte);

    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = builder.Configuration["KeycloakJwtAuth:Issuer"],
        ValidAudience = builder.Configuration["KeycloakJwtAuth:Audience"],
        ValidAlgorithms = new List<string>() { "RS256" },
        AuthenticationType = "JWT",
        IssuerSigningKey = new RsaSecurityKey(rsa)
    };

    options.Events = new JwtBearerEvents()
    {
        OnMessageReceived = context =>
        {
            var Token = context.Request.Headers["Authorization"].ToString();
            context.Token = Token;
            return Task.CompletedTask;
        },
        OnAuthenticationFailed = context =>
        {
            return Task.CompletedTask;
        },
        OnChallenge = context =>
        {
            return Task.CompletedTask;
        },
        OnTokenValidated = context =>
        {
            return Task.CompletedTask;
        }
    };

    options.Validate();

})
.AddJwtBearer("pas", options =>
        {
//secound auth method (validate jwt token with securityKey ) 
            options.RequireHttpsMetadata = false;

            var securityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(builder.Configuration["PasJwtAuth:key"]));

            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
               // ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = builder.Configuration["PasJwtAuth:Issuer"],
                ValidAudience = builder.Configuration["PasJwtAuth:Audience"],
                AuthenticationType = "JWT",
                IssuerSigningKey = securityKey,

            };

            options.Events = new JwtBearerEvents()
            {
                OnMessageReceived = context =>
                {
                    var Token = context.Request.Headers["Authorization"].ToString();
                    context.Token = Token;
                    return Task.CompletedTask;
                },
                OnAuthenticationFailed = context =>
                {
                    return Task.CompletedTask;
                },
                OnChallenge = context =>
                {
                    return Task.CompletedTask;
                },
                OnTokenValidated = context =>
                {
                    return Task.CompletedTask;
                }
            };

            options.Validate();
        })
.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("basic",null)//therd auth method (validate basic auth)

and then define auth Selector,like this:

.AddPolicyScheme("UNKNOWN", "UNKNOWN", options =>
{
options.ForwardDefaultSelector = context =>
{
    string authorization = context.Request.Headers[HeaderNames.Authorization];

    {
      
        var jwtHandler = new JwtSecurityTokenHandler();
        if (jwtHandler.CanReadToken(authorization))
        {
            var issuer = jwtHandler.ReadJwtToken(authorization).Issuer;
            if (issuer == builder.Configuration["PasJwtAuth:Issuer"]) 
            {
                return "pas";
            }
            else if (issuer == builder.Configuration["KeycloakJwtAuth:Issuer"]) 
            {
                return "keycloak";
            }

        }
    }

    return "basic";
};
});

if you needed authorization,you sould be use somthing like this:

builder.Services.AddAuthorization(opt =>
{
var policy = opt.DefaultPolicy = new AuthorizationPolicyBuilder()
       .RequireAuthenticatedUser()
       .AddAuthenticationSchemes("keycloak", "pas", "basic")
       .Build();

opt.AddPolicy("user", policy);
opt.AddPolicy("backoffice", policy => policy.RequireRole("backoffice"));
});

if you need about implementation of BasicAuthenticationHandler, read this article

and to config Swagger UI, follow this way:

builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo() { Version = "V1", Title = "Sepehr Customer Club" });

c.AddSecurityDefinition("basic", new OpenApiSecurityScheme
{
    Description = "Basic auth added to authorization header",
    Name = "Authorization",
    In = ParameterLocation.Header,
    Scheme = "basic",
    Type = SecuritySchemeType.Http
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
    {
        new OpenApiSecurityScheme
        {
            Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "basic" }
        },
        new string[] { }
    }
});

c.AddSecurityDefinition("pas", new OpenApiSecurityScheme
{
    Description = "Please insert JWT with pas Bearer into field",
    Name = "Authorization",
    In = ParameterLocation.Header,
    Scheme = "pas",
    Type = SecuritySchemeType.ApiKey,
    BearerFormat = "JWT"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
    {
        new OpenApiSecurityScheme
        {
            Reference = new OpenApiReference{Type = ReferenceType.SecurityScheme, Id = "pas"}
        },
        new string[] { }
    }
});

c.AddSecurityDefinition("keycloak", new OpenApiSecurityScheme
{
    Description = "Please insert JWT with keycloak Bearer into field",
    Name = "Authorization",
    In = ParameterLocation.Header,
    Scheme = "keycloak",
    Type = SecuritySchemeType.ApiKey,
    BearerFormat = "JWT"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
    {
        new OpenApiSecurityScheme
        {
            Reference = new OpenApiReference{Type = ReferenceType.SecurityScheme, Id = "keycloak"}
        },
        new string[] { }
    }
});

});
Majid325
  • 34
  • 5