Role-based authorization with IdentityServer4

I am trying to implement "role-based authorization" using IdentityServer4 to provide access to my user-role-based API.

For example, I want to have two roles for the user, that is, FreeUser and PaidUser, and I want to provide access to the API through the authorization attribute using [Authorize (Roles = "FreeUser")), please help me how can I achieve this.

I have the following solution structure:

  • IdentityServer
  • Webapi
  • Javascript client

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

Sights

  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 log into the user system 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 input stream is working fine, and I can log in successfully, and I can get the role in the access token.

enter image description here

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

+8
asp.net-mvc asp.net-core identityserver4
source share
3 answers

Given that you did not provide a configuration object for the javascript client, I assume that you configured the scope as follows.

 scope:"openid profile api1 role" 

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

Add the application for the role to the api1 area 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 to help debug this issue. implementing roles on identity server 4 with asp.net id

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

+5
source share

Change new Claim("role","FreeUser") to new Claim(ClaimTypes.Role, "FreeUser")

Or create a policy like this:

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

and use it:

 Authorize[(Policy = "FreeUser")] 
+2
source share

I wrote a sample of this post

Identity Server 4: Adding Access Token Claims

I tested with roles and claimed to be able to use [Authorize (Role = "SuperAdmin, Admin")] in both the client web application and the API application.

0
source share

All Articles