title: implementing roles in identity server 4 with asp.net identity
body: <p>I am working on an asp.net MVC application with identity server 4 as token service. I have an api as well which has some secure resources. I want to implement roles (Authorization) for api. I want to make sure that only an authorized resource with valid role can access an api end point otherwise get 401 (unauthorized error).</p>
  
  <p>Here are my configurations:</p>
  
  <p><strong>Client</strong></p>
  
  <pre><code>         new Client()
              {
                  ClientId = "mvcClient",
                  ClientName = "MVC Client",                    
                  AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
  
                  ClientSecrets = new List&lt;Secret&gt;()
                  {
                      new Secret("secret".Sha256())
                  },
  
                  RequireConsent = false;
  
                  // where to redirect to after login
                  RedirectUris = { "http://localhost:5002/signin-oidc" },
                  // where to redirect to after logout
                  PostLogoutRedirectUris = { "http://localhost:5002" },
  
                  AllowedScopes =
                  {
                      StandardScopes.OpenId.Name,
                      StandardScopes.Profile.Name,
                      StandardScopes.OfflineAccess.Name,
                      StandardScopes.Roles.Name,
                      "API"
                  }
              }
  </code></pre>
  
  <p><strong>Scopes</strong></p>
  
  <pre><code> return new List&lt;Scope&gt;()
              {
                  StandardScopes.OpenId, // subject id
                  StandardScopes.Profile, // first name, last name
                  StandardScopes.OfflineAccess,  // requesting refresh tokens for long lived API access
                 StandardScopes.Roles,
                  new Scope()
                  {
                      Name = "API",
                      Description = "API desc",
                       Type = ScopeType.Resource,
                      Emphasize = true,
                      IncludeAllClaimsForUser = true,
                      Claims = new List&lt;ScopeClaim&gt;
                      {
                          new ScopeClaim(ClaimTypes.Name),      
                          new ScopeClaim(ClaimTypes.Role)
                      }
                  }
              };
  </code></pre>
  
  <p><strong>User</strong></p>
  
  <pre><code>new InMemoryUser()
                  {
                      Subject = "1",
                      Username = "testuser",
                      Password = "password",
                      Claims = new List&lt;Claim&gt;()
                      {
                          new Claim("name", "Alice"),
                          new Claim("Website", "http://alice.com"),
                           new Claim(JwtClaimTypes.Role, "admin")
  
                      }
                  }
  </code></pre>
  
  <p>and in server startup i added this:</p>
  
  <p>services.AddIdentityServer()
              .AddTemporarySigningCredential()
               .AddSigningCredential(cert)
              .AddInMemoryClients(Config.GetClients())
              .AddInMemoryScopes(Config.GetScopes())
              .AddInMemoryUsers(Config.GetUsers())</p>
  
  <p>in api startup, i have this:</p>
  
  <pre><code>  app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions()
              {
                  Authority = "http://localhost:5000",
                  ScopeName = "NamfusAPI",
                  RequireHttpsMetadata = false
              });
  </code></pre>
  
  <p>in api controller, i have this:</p>
  
  <pre><code> [Authorize(Roles = "admin")]
          public IActionResult Get()
          {
              return new JsonResult(from c in User.Claims select new {c.Type, c.Value });
          }
  </code></pre>
  
  <p>in MVC client startup, i have this:</p>
  
  <pre><code> JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
  
   app.UseCookieAuthentication(new CookieAuthenticationOptions()
              {
                  AuthenticationScheme = "Cookies"
              });
  
  
              var oidcOptions = new OpenIdConnectOptions()
              {
                  AuthenticationScheme = "oidc",
                  SignInScheme = "Cookies",
  
                  Authority = "http://localhost:5000",
                  RequireHttpsMetadata = false,
  
                  ClientId = "mvcClient",
                  ClientSecret = "secret",
                  SaveTokens = true,
                  GetClaimsFromUserInfoEndpoint = true,
                  ResponseType = "code id_token", // hybrid flow
  
              };
  
  
              oidcOptions.Scope.Clear();
              oidcOptions.Scope.Add("openid");
              oidcOptions.Scope.Add("profile");
              oidcOptions.Scope.Add("NamfusAPI");
              oidcOptions.Scope.Add("offline_access");
              oidcOptions.Scope.Add("roles");
  </code></pre>
  
  <p>I am trying to call the api like this:</p>
  
  <pre><code>public async Task&lt;IActionResult&gt; CallApiUsingUserAccessToken()
          {
              var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");
  
              var client = new HttpClient();
              client.SetBearerToken(accessToken);
              var content = await client.GetStringAsync("http://localhost:5001/identity");
  
              ViewBag.Json = JArray.Parse(content).ToString();
              return View("json");
          } 
  </code></pre>
  
  <p>I get access token but when call is made to api (identity/get), I get 302 error Forbidden (in chrome network it shows 500 internal server error). If I change API Authorize attribute from</p>
  
  <pre><code>  [Authorize(Roles = "admin")]
              public IActionResult Get()
  </code></pre>
  
  <p>to (without role):</p>
  
  <pre><code> [Authorize]
          public IActionResult Get()
  </code></pre>
  
  <p>it works and I get data from api in mvc app. How can I apply roles in this code. </p>
  
  <p>Please suggest.</p>