Home > Back-end >  blazor webassembly wasm windows authentication / negotiate jwt? api protection
blazor webassembly wasm windows authentication / negotiate jwt? api protection

Time:07-08

im building some blazor wasm app i have to use windows autch because it is for corporate users only. so i have

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();

and i have some user controller that take care of getting username. now i want to protect whole api so user canot use my api (because they are domain authenticated) ,only this WASM shoult be able to use this api and swagger in development.

what is best practise for this ? jwt also ? just for api protection and not pure user authentication ?

i did generated some jwt

    [HttpGet]
    [Authorize]
    [Route("GetUser")]
    public UserModel GetUser()
    {

        string? login =  httpContextAccessor!.HttpContext!.User?.Identity?.Name?.Replace("domain\\", "");

        return new UserModel{ UserName=login , JWT = CreateJWT(login)};
    }

    private string? CreateJWT(string? userName)
    {
        if (userName == null) return null;

        var secretkey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(this.appSettings.JWTSettings!.Secret!)); 
        var credentials = new SigningCredentials(secretkey, SecurityAlgorithms.HmacSha256);

        var claims = new[] 
        {
            new Claim(ClaimTypes.Name, userName), 
            new Claim(JwtRegisteredClaimNames.Sub, userName)
        };

        var token = new JwtSecurityToken(issuer: "xxx", audience: "xxx", claims: claims, expires: DateTime.Now.AddMinutes(int.Parse(this.appSettings.JWTSettings.ExpireTime!)), signingCredentials: credentials);
        return new JwtSecurityTokenHandler().WriteToken(token);
    }

}

but how to force api to check this jwt also ? i tryied

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => 
{
options.TokenValidationParameters = new TokenValidationParameters
{
    ValidateAudience = true,
    ValidAudience = "xxx",
    ValidateIssuer = true,
    ValidIssuer = "xxx",
    ValidateLifetime = true,
    ValidateIssuerSigningKey = true,
    IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(a.JWTSettings.Secret!)) 
};
});

but this did not changed anything. can the app have two times builder.Services.AddAuthentication ?

if no then i need to build some custom middleware ? or is there some better soliution ?

thanks and regards

CodePudding user response:

ok so for future searchers. for this to work this way i wanted we need :

builder.Services.AddAuthentication((options) =>
{
options.DefaultAuthenticateScheme = "JwtBearer";
options.DefaultChallengeScheme = "JwtBearer";
}).AddJwtBearer(options =>
{
  options.TokenValidationParameters = new TokenValidationParameters
{
    ValidateAudience = true,
    ValidateIssuer = true,
    ValidIssuer = builder.Configuration["JWT:Issuer"],
    ValidAudience = builder.Configuration["JWT:Issuer"],
    ValidateLifetime = true,
    ValidateIssuerSigningKey = true,
    IssuerSigningKey = new 
SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(builder.Configuration["JWT:Key"]))
};
}).AddNegotiate();

then i added

 builder.Services.AddAuthorization(options =>
 {    
  var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme);
  defaultAuthorizationPolicyBuilder = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
  options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
 }); 

and

app.MapControllers().RequireAuthorization();

this add automaticly invisible

[Authorize(AuthenticationSchemes=JwtBearerDefaults.AuthenticationScheme)]

to all my controllers

and finaly for just getUser method where this jwt is generated and windows username is grabbed need

[Authorize(AuthenticationSchemes = NegotiateDefaults.AuthenticationScheme)]
  • Related