简体   繁体   中英

blazor webassembly wasm windows authentication / negotiate+ jwt? api protection

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

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)]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM