web-dev-qa-db-fra.com

Autorisation basée sur les rôles avec IdentityServer4

J'essaie d'implémenter une "autorisation basée sur le rôle" en utilisant IdentityServer4 pour donner accès à mon API en fonction des rôles d'utilisateur. 

Par exemple, je veux avoir deux rôles pour l'utilisateur, à savoir FreeUser et PaidUser, et je souhaite donner l'accès à l'API via l'attribut Autoriser à l'aide de [Authorize (Roles = "FreeUser"))], Aidez-moi, s'il vous plaît. Comment puis-je y parvenir? .

J'ai la structure de solution suivante:

  1. IdentityServer
  2. WebApi
  3. Client javascript

J'ai enregistré mon client Javascript comme suit:

 new Client
            {
                ClientId = "js",
                ClientName = "javascript client",
                AllowedGrantTypes = GrantTypes.Implicit,
                AllowAccessTokensViaBrowser= true,
                RedirectUris = {"http://localhost:5004/callback.html"},
                PostLogoutRedirectUris = {"http://localhost:5004/index.html"},
                AllowedCorsOrigins = {"http://localhost:5004"},

                AllowedScopes =
                {
                    StandardScopes.OpenId.Name,
                    StandardScopes.Profile.Name,
                    "api1",
                    "role",
                    StandardScopes.AllClaims.Name
                }
            }

Scopes

 return new List<Scope>
        {
            StandardScopes.OpenId,
            StandardScopes.Profile,

            new Scope
            {
                Name = "api1",
                Description = "My API"
            },
           new Scope
           {
               Enabled = true,
               Name  = "role",
               DisplayName = "Role(s)",
               Description = "roles of user",
               Type = ScopeType.Identity,
               Claims = new List<ScopeClaim>
               {
                   new ScopeClaim("role",false)
               }
           },
           StandardScopes.AllClaims
        };

Utilisateurs

 return new List<InMemoryUser>
        {
            new InMemoryUser
            {
                Subject = "1",
                Username = "alice",
                Password = "password",

                Claims = new List<Claim>
                {
                    new Claim("name", "Alice"),
                    new Claim("website", "https://alice.com"),
                    new Claim("role","FreeUser")
                }
            },
            new InMemoryUser
            {
                Subject = "2",
                Username = "bob",
                Password = "password",

                Claims = new List<Claim>
                {
                    new Claim("name", "Bob"),
                    new Claim("website", "https://bob.com"),
                    new Claim("role","PaidUser")
                }
            }
        };

WebApi Startup.cs 

  public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();


        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
        app.UseCors("default");
        app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
        {
            Authority = "http://localhost:5000",
            ScopeName = "api1",
            //  AdditionalScopes = new List<string> { "openid","profile", "role" },
            RequireHttpsMetadata = false
        });

        app.UseMvc();
    }

Contrôleur Web Api

namespace Api.Controllers
{
 [Route("[controller]")]

public class IdentityController : ControllerBase
{
    [HttpGet]
    [Authorize(Roles = "PaidUser")]
    public IActionResult Get()
    {
        return new JsonResult(from c in User.Claims select new { c.Type,    c.Value });
    }

    [Authorize(Roles = "FreeUser")]
    [HttpGet]
    [Route("getfree")]
    public IActionResult GetFreeUser()
    {
        return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
    }
}
}

Javascript Client app.js J'essaie de connecter l'utilisateur via IdentityServer et de faire une demande d'API.

var mgr = new Oidc.UserManager(config);
mgr.getUser().then(function (user) {
if (user) {
    log("User logged in", user.profile);
} else {
    log("User is not logged in.");
}
});

function login() {
  mgr.signinRedirect();
 }

function api() {
mgr.getUser().then(function (user) {
    var url = "http://localhost:5001/identity/getfree";

    var xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = function () {
        log(xhr.status, JSON.parse(xhr.responseText));
    };

    xhr.setRequestHeader("Authorization", "Bearer " + user.access_token);
    xhr.send();
  });
 }

 function logout() {
   mgr.signoutRedirect();
 }

Le flux de connexion fonctionne correctement et je peux me connecter avec succès et je peux recevoir le rôle dans le jeton d'accès.

 enter image description here

Lorsque je fais une demande à l'API en cliquant sur le bouton (Appeler Api), j'obtiens l'erreur suivante ..  enter image description here

16
muhammad waqas

Étant donné que vous n’avez pas fourni d’objet config pour le client javascript, je suppose que votre étendue est configurée comme suit. 

scope:"openid profile api1 role"

Je pense que la principale raison de votre problème est que la revendication de rôle n’est pas incluse dans votre clé d’accès.

Ajoutez la revendication de rôle à la portée d'api1 comme suit pour l'inclure dans le jeton d'accès.

             new Scope
                {
                    Name = "api1",
                    DisplayName = "API1 access",
                    Description = "My API",
                    Type = ScopeType.Resource,
                    IncludeAllClaimsForUser = true,
                    Claims = new List<ScopeClaim>
                    {
                        new ScopeClaim(ClaimTypes.Name),
                        new ScopeClaim(ClaimTypes.Role)
                    }
                }

Vous pouvez lire ma réponse ici pour obtenir de l'aide pour résoudre le problème . implémentation de rôles dans le serveur d'identité 4 avec asp.net identity

La solution de travail complète est ici . https://github.com/weliwita/IdentityServer4.Samples/tree/40844310

10
rawel

Remplacez new Claim("role","FreeUser") par new Claim(ClaimTypes.Role, "FreeUser")

Ou créez une politique comme celle-ci:

services.AddAuthorization(options =>
{
    options.AddPolicy("FreeUser", policy => policy.RequireClaim("role", "FreeUser"));
});

et l'utiliser:

Authorize[(Policy = "FreeUser")]
5
adem caglin

J'ai écrit un échantillon sur ce post 

Identity Server 4: ajout de revendications au jeton d'accès

J'ai testé avec des rôles et des revendications, je peux également utiliser [Autoriser (rôle = "SuperAdmin, Admin")] dans les applications Web client et API.

0
Mirak