3
votes

Jeton de support JWT ASP.Net Core 3.0 Aucun SecurityTokenValidator disponible

J'utilise une API ASP.Net Core 3.0 avec EntityFramework Core comme UserStorage. Startup.cs:

[Route("api/videos/add")]
[Authorize(Roles = "Admin")]
[HttpPost]
public async Task<IActionResult> AddVideo()
{
    using (var reader = new StreamReader(Request.Body))
    {
        var body = await reader.ReadToEndAsync();
        var video = JsonConvert.DeserializeObject<Video>(body);
        await videoService.AddVideo(video);
        return Ok();
    }
}

Voici mon code émettant un jeton JWT:

public async Task<IActionResult> Login()
        {
            using (var reader = new StreamReader(Request.Body))
            {
                var body = await reader.ReadToEndAsync();
                var cred = JsonConvert.DeserializeObject<Credentials>(body);
                var result = (await userService.LoginUser(cred.userName, cred.password));
                if (result == 200)
                {

                    var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration.GetSection("Secrets")["jwt"]));
                    var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256Signature);

                    var roles = await userService.GetRoleFromUsername(cred.userName);
                    var rolesString = JsonConvert.SerializeObject(roles);

                    var tokeOptions = new JwtSecurityToken(
                                issuer: "http://localhost:44352",
                                audience: "http://localhost:44352",
                                claims: new List<Claim>(new List<Claim> {
                                        new Claim("userName",cred.userName),
                                        new Claim("roles", rolesString)
                                }),
                                expires: DateTime.Now.AddHours(1),
                                signingCredentials: signinCredentials
                    );

Ceci est mon appel d'API utilisant l'autorisation: p >

        public void ConfigureServices(IServiceCollection services)
            {
             using Microsoft.AspNetCore.Authentication.JwtBearer;
             using Microsoft.AspNetCore.Builder;
             using Microsoft.AspNetCore.Hosting;
             using Microsoft.AspNetCore.Identity;
             using Microsoft.AspNetCore.SpaServices.AngularCli;
             using Microsoft.EntityFrameworkCore;
             using Microsoft.Extensions.Configuration;
             using Microsoft.Extensions.DependencyInjection;
             using Microsoft.Extensions.Hosting;
             using Microsoft.IdentityModel.Tokens;
             using System;
             using System.Collections.Generic;
             using System.Linq;
             using System.Text;
             using System.Threading.Tasks;
                .
                .
                .

                //Add Identity Provider with EntityFramework
                services.AddIdentity<User, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDBContext>()
                .AddDefaultTokenProviders();

                //Initialize EntityFramework
                services.AddDbContext<ApplicationDBContext>(options => options.UseSqlite(Configuration.GetConnectionString("localDB")));

                //Initialize JWT Authentication
                services.AddAuthentication(options => {
                    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                }).AddJwtBearer(jwtBearerOptions =>
                {
                    jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters()
                    {
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true,

                        ValidIssuer = "http://localhost:44352",
                        ValidAudience = "http://localhost:44352",
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetSection("Secrets")["jwt"]))
                    };
                }
                );
                services.AddMvc(options => options.EnableEndpointRouting = false)
                    .AddNewtonsoftJson();

                // In production, the Angular files will be served from this directory
                services.AddSpaStaticFiles(configuration =>
                {
                    configuration.RootPath = "ClientApp/dist";
                });
            }

            .
            .
            .


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

                //Enable Authentication
                app.UseAuthentication();
                app.UseAuthorization();

                .
                .
                .

                app.UseMvc(routes =>
                {
                    routes.MapRoute(
                        name: "default",
                        template: "{controller}/{action=Index}/{id?}");
                });


    .
    .
    .

Mes packages NuGet sont:

  • Microsoft.EntityFrameworkCore {3.0.0-preview5.19227.1}
  • Microsoft.EntityFrameworkCore.Sqlite {3.0.0-preview5.19227.1}
  • Microsoft.AspNetCore.Authentication.JwtBearer {3.0.0-preview4-19216-03}
  • Microsoft.EntityFrameworkCore.Sqlite.Core {3.0.0-preview5.19227.1}
  • Microsoft.NETCore.Platforms {3.0.0-preview4.19212.13}
  • Microsoft.AspNetCore.Mvc.NewtonsoftJson {3.0.0-preview5-19227-01}
  • Microsoft.AspNetCore.SpaServices.Extensions {3.0.0-preview5-19227-01}
  • Microsoft.AspNetCore.Identity.EntityFrameworkCore {3.0.0-preview5-19227-01}
  • runtime.win-x64.Microsoft.NETCore.DotNetAppHost {3.0.0-preview4-27615-11}

Le problème que j'ai, c'est que si j'appelle cette partie API, j'obtiens l'erreur:

Information: le porteur n'a pas été authentifié. Message d'échec: Aucun SecurityTokenValidator disponible pour le jeton:

Toute aide serait très appréciée, car je ne trouve pas l'erreur


5 commentaires

Vous pouvez essayer ce lien


Merci pour votre réponse. Malheureusement, je n'utilise pas OpenID Connect


N'y a-t-il pas de moyen «vanille» d'accomplir cela?


Utilisez ClaimTypes.Role au lieu de "roles" dans la liste des revendications. Quel est le contenu de rolesString ?


Merci pour votre réponse. Le contenu de rolesString est une List , qui est convertie en chaîne par JsonConvert.SerializeObject ()


3 Réponses :


3
votes

Essayez d'utiliser ClaimTypes.Role au lieu de roles si vous souhaitez ajouter un rôle comme revendication.

var tokeOptions = new JwtSecurityToken(
                            issuer: "http://localhost:44352",
                            audience: "http://localhost:44352",
                            claims: new List<Claim>(new List<Claim> {
                                    new Claim("userName",cred.userName),
                                    new Claim(ClaimTypes.Role, "Admin")                                      
                            }),
                            expires: DateTime.Now.AddHours(1),
                            signingCredentials: signinCredentials
                );


3 commentaires

Merci pour votre réponse. Malheureusement, cela ne l'a pas fait. J'ai toujours la même erreur


Cela fonctionne bien dans mon projet asp.net core 2.2 lorsque je teste avec postman.Comment testez-vous l'API?


Je teste avec le SPA Angular7 que je développe



2
votes

Grâce à Xing Zou, je suis arrivé à la racine de l'erreur. Le problème était que j'ai envoyé le jeton porteur avec des guillemets.

 Request

L'erreur dans l'API a maintenant disparu, le problème est que l'autorisation échoue maintenant dans l'API et elle renvoie 403.

MODIFIER:

J'ai trouvé le problème concernant l'erreur 403. Il semble que vous ne soyez autorisé à envoyer qu'UN rôle dans le jeton de support pour ASP.Net pour le valider. Le type de retour de userManager.GetRolesAsync suggère qu'un utilisateur peut avoir plusieurs rôles qui peuvent être inclus dans un jeton de support JWT.

Cela signifie que mon problème est résolu.

Je tiens à remercier tout le monde pour leurs réponses. Je ne l'aurais pas eu sans toi!


0 commentaires

0
votes

J'ai géré ce problème comme ceci:

client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.Replace("\"", "")}");

Ce n'est pas la meilleure solution, mais cela a fonctionné.


0 commentaires