Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I am trying to implement "Role Based Authorization" using IdentityServer4 to give access to my API based on the user roles.

For example , I want to have two roles for the user i.e. FreeUser and PaidUser and want to give access to the API through the Authorize Attribute using [Authorize(Roles = "FreeUser"))], Kindly help me that How can I achieve this.

I have the following solution structure :

  1. IdentityServer
  2. WebApi
  3. Javascript Client

I have registered my Javascript client as follows:

 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
        };

Users

 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();
    }

Web Api controller

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 Here I am trying to login the user through IdentityServer and make an API Request.

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();
 }

The Login flow works fine and I can login successfully, and I can receive the role in the access token.

enter image description here

When I make a request to the API by clicking the button (Call Api) then I get the following error.. enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
490 views
Welcome To Ask or Share your Answers For Others

1 Answer

Given that you have not provided config object for javascript client, I assume you have scope configured as follows.

scope:"openid profile api1 role"

I believe that the main reason for your issue is that role claim is not included in your access token.

Add role claim to api1 scope as follows to include it in the access token.

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

You can read my answer here for help debug the issue. implementing roles in identity server 4 with asp.net identity

The complete working solution is here. https://github.com/weliwita/IdentityServer4.Samples/tree/40844310


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...