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:
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
3 Réponses :
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
);
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
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.
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!
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é.
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.Roleau lieu de"roles"dans la liste des revendications. Quel est le contenu derolesString?Merci pour votre réponse. Le contenu de rolesString est une List, qui est convertie en chaîne par JsonConvert.SerializeObject ()