Je suis nouveau sur IdentityServer et j'ai été confronté à ce problème toute la journée. À tel point que je suis presque sur le point d'abandonner. Je sais que cette question a été posée maintes et maintes fois et j'ai essayé de nombreuses solutions différentes, mais aucune ne semble fonctionner. J'espère que vous pourrez m'aider à me mettre sur la bonne voie.
J'ai d'abord installé les modèles d'IdentityServer4 en exécutant dotnet new -i identityserver4.templates
et créé un nouveau projet avec le modèle is4aspid en exécutant dotnet new is4aspid -o IdentityServer
.
Après cela, j'ai créé une nouvelle base de données IdentityServer et j'ai lancé les migrations. À ce moment-là, j'avais une structure de base de données d'identité par défaut.
Dans Config.cs, j'ai modifié MVC client
à ce qui suit :
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.Implicit,
ClientSecrets = { new Secret("47C2A9E1-6A76-3A19-F3C0-S37763QB36D9".Sha256()) },
RedirectUris = { "https://localhost:44307/signin-oidc" },
FrontChannelLogoutUri = "https://localhost:44307/signout-oidc",
PostLogoutRedirectUris = { "https://localhost:44307/signout-callback-oidc" },
AllowOfflineAccess = true,
AllowedScopes = { "openid", "profile", "api1", JwtClaimTypes.Role }
},
Et a changé le GetApis
à cette méthode :
public static IEnumerable<ApiResource> GetApis()
{
return new ApiResource[]
{
new ApiResource("api1", "My API #1", new List<string>() { "role" })
};
}
Bien entendu, il n'y avait pas encore d'utilisateurs dans la base de données. J'ai donc ajouté un formulaire d'inscription et enregistré deux utilisateurs fictifs, l'un avec le nom d'utilisateur suivant admin@example.com
et un autre avec le nom d'utilisateur subscriber@example.com
.
Pour attribuer les rôles à ces utilisateurs, j'ai créé la méthode suivante dans Startup.cs.
private async Task CreateUserRoles(IServiceProvider serviceProvider) {
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var UserManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
IdentityResult adminRoleResult;
IdentityResult subscriberRoleResult;
bool adminRoleExists = await RoleManager.RoleExistsAsync("Admin");
bool subscriberRoleExists = await RoleManager.RoleExistsAsync("Subscriber");
if (!adminRoleExists) {
adminRoleResult = await RoleManager.CreateAsync(new IdentityRole("Admin"));
}
if(!subscriberRoleExists) {
subscriberRoleResult = await RoleManager.CreateAsync(new IdentityRole("Subscriber"));
}
ApplicationUser userToMakeAdmin = await UserManager.FindByNameAsync("admin@example.com");
await UserManager.AddToRoleAsync(userToMakeAdmin, "Admin");
ApplicationUser userToMakeSubscriber = await UserManager.FindByNameAsync("subscriber@example.com");
await UserManager.AddToRoleAsync(userToMakeSubscriber, "Subscriber");
}
Dans le Configure
de la même classe, j'ajoute le paramètre IServiceProvider services
et appelé la méthode ci-dessus comme suit : CreateUserRoles(services).Wait();
. À ce moment-là, ma base de données contenait deux rôles.
Ensuite, j'ai créé une nouvelle solution (dans le même projet) et, dans le fichier Startup.cs de cette solution, j'ai ajouté ce qui suit dans la balise ConfigureServices
méthode.
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options => {
options.SaveTokens = true;
options.ClientId = "mvc";
options.ClientSecret = "32D7A7W0-0ALN-2Q44-A1H4-A37990NN83BP";
options.RequireHttpsMetadata = false;
options.Authority = "http://localhost:5000/";
options.ClaimActions.MapJsonKey("role", "role");
});
Après cela, j'ai ajouté app.UseAuthentication();
dans le Configure
de la même classe.
J'ai ensuite créé une nouvelle page avec les instructions if suivantes.
if(User.Identity.IsAuthenticated) {
<div>Yes, user is authenticated</div>
}
if(User.IsInRole("ADMIN")) {
<div>Yes, user is admin</div>
}
Je me suis connecté avec admin@example.com
mais la deuxième instruction if renvoie False
. J'ai inspecté toutes les revendications en les passant en boucle comme ceci.
@foreach (var claim in User.Claims) {
<dt>@claim.Type</dt>
<dd>@claim.Value</dd>
}
Mais il n'y avait aucune revendication de rôle à trouver, seulement sid, sub, idp, preferred_username et name.
J'ai essayé d'y introduire le rôle de manière à ce que la deuxième instruction if renvoie True, mais après de multiples essais, je n'ai pas encore réussi à le faire fonctionner. Quelqu'un peut-il voir ce que je dois faire pour que cela fonctionne ? Je suis un débutant absolu dans IdentityServer4 et je fais de mon mieux pour le comprendre. Toute aide sera appréciée. Merci d'avance !
EDIT 1 :
Merci à cette question y cette question J'ai l'impression d'être sur la bonne voie. J'ai fait quelques modifications mais je n'arrive toujours pas à le faire fonctionner. Je viens d'essayer ce qui suit.
-
J'ai créé une nouvelle classe ProfileService dans mon projet IdentityServer avec le contenu suivant.
public class MyProfileService : IProfileService { public MyProfileService() { } public Task GetProfileDataAsync(ProfileDataRequestContext context) { var roleClaims = context.Subject.FindAll(JwtClaimTypes.Role); List<string> list = context.RequestedClaimTypes.ToList(); context.IssuedClaims.AddRange(roleClaims); return Task.CompletedTask; }
public Task IsActiveAsync(IsActiveContext context) { return Task.CompletedTask; } }
Ensuite, j'ai enregistré cette classe dans la méthode ConfigureServices en ajoutant la ligne services.AddTransient<IProfileService, MyProfileService>();
. Après cela, j'ai ajouté une nouvelle ligne à la méthode GetIdentityResources, qui ressemble maintenant à ceci.
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource("roles", new[] { "role" })
};
}
J'ai également ajouté les rôles à mon client Mvc comme suit : AllowedScopes = { "openid", "profile", "api1", "roles" }
.
Ensuite, je suis passé à l'autre projet et j'ai ajouté les lignes suivantes dans l'oidc .AddOpenIdConnect.
options.ClaimActions.MapJsonKey("role", "role", "role");
options.TokenValidationParameters.RoleClaimType = "role";
Mais je n'arrive toujours pas à le faire fonctionner comme je le voudrais. Quelqu'un sait-il ce qui me manque ?