'With identityserver4, read, write, delete operations according to the user's authority

I am authenticating with identityserver4. I am using database sql server. I have completed migration processes, user registration and user authorizations.

There is a user I have specified and I have not given the user read permission.

I reported this to the API side, but it can read even if the user has no authorization.

How can I fix this? [Authorize(Policy = "ReadPurchasingManagement")]

I coded the config file as follows Config.cs

    using IdentityModel;
    using IdentityServer4;
    using IdentityServer4.Models;
    using System;
    using System.Collections.Generic;

    namespace IdentityServer
    {
        public static class Config
        {
            #region ApiResources
            public static IEnumerable<ApiResource> GetApiResources()
            {
                return new List<ApiResource>() {
                    new ApiResource("resource_purchasing"){Scopes= {"purchasing.create", "purchasing.read", "purchasing.update", "purchasing.delete"}},
                    new ApiResource(IdentityServerConstants.LocalApi.ScopeName)
                };
            }
            #endregion


            #region Identity Resource
            public static IEnumerable<IdentityResource> GetIdentityResources()
            {
                return new List<IdentityResource>()
                {
                    new IdentityResources.OpenId(),
                    new IdentityResources.Email(),
                    new IdentityResources.Profile(),
                    new IdentityResources.Phone(),
                    new IdentityResources.Address(),
                    new IdentityResource()
                    {
                        Name="roles",
                        DisplayName="Roles",
                        Description= "User roles",
                        UserClaims = { JwtClaimTypes.Role },
                    }
                };
            }
            #endregion

            #region Scopes
            public static IEnumerable<ApiScope> GetApiScope()
            {
                return new List<ApiScope>()
                {
                    #region Purchasing Management Permissions
                    new ApiScope("purchasing.create", "PM create"),
                    new ApiScope("purchasing.read", "PM read"),
                    new ApiScope("purchasing.update", "PM update"),
                    new ApiScope("purchasing.delete", "PM delete"),
                    new ApiScope(IdentityServerConstants.LocalApi.ScopeName),

                 #endregion
                };
            }
            #endregion


            #region Clients
            public static IEnumerable<Client> GetClients()
            {
                return new List<Client>()
                {
                    new Client()
                    {
                        ClientId = "PurchasingClient",
                        ClientSecrets = new[] { new Secret("secret".Sha256())},
                        ClientName = "Purchasing Management",
                        AllowedGrantTypes= GrantTypes.ResourceOwnerPasswordAndClientCredentials,
                        Enabled = true,
                        AccessTokenType = AccessTokenType.Jwt,
                        AlwaysSendClientClaims = true,
                        UpdateAccessTokenClaimsOnRefresh = true,
                        AlwaysIncludeUserClaimsInIdToken = true,
                        AllowAccessTokensViaBrowser = true,
                        IncludeJwtId = true,

                         AllowedScopes = {
                            IdentityServerConstants.LocalApi.ScopeName,
                            IdentityServerConstants.StandardScopes.Email,
                            IdentityServerConstants.StandardScopes.OpenId,
                            IdentityServerConstants.StandardScopes.Profile,
                            IdentityServerConstants.StandardScopes.Phone,
                            IdentityServerConstants.StandardScopes.Address,
                            IdentityServerConstants.StandardScopes.OfflineAccess,
                            IdentityServerConstants.LocalApi.ScopeName,
                            "roles",

                            "resource_purchasing",
                            "purchasing.create", 
                            "purchasing.read", 
                            "purchasing.update", 
                            "purchasing.delete"
                        },

                        AllowOfflineAccess=true,
                        AccessTokenLifetime= 4*60*60,
                        RefreshTokenExpiration=TokenExpiration.Absolute,

                        AbsoluteRefreshTokenLifetime=(int)(DateTime.Now.AddDays(60)-DateTime.Now).TotalSeconds,
                        RefreshTokenUsage = TokenUsage.ReUse
                    }
                };
            }
            #endregion
        }
    }

Startup.cs

    using IdentityServer.Data;
    using IdentityServer.Models;
    using IdentityServer.Services;
    using IdentityServer4;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using System.Reflection;

    namespace IdentityServer
    {
        public class Startup
        {
            public IWebHostEnvironment Environment { get; }
            public IConfiguration Configuration { get; }

            public Startup(IWebHostEnvironment environment, IConfiguration configuration)
            {
                Environment = environment;
                Configuration = configuration;
            }

            public void ConfigureServices(IServiceCollection services)
            {
                services.AddLocalApiAuthentication();
                services.AddControllersWithViews();
                services.AddDbContext<ApplicationDbContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("IdentityServerDbConnection")));


                #region Identity Roles
                services.AddIdentity<ApplicationUser, IdentityRole>(options =>
                {
                    options.Password.RequiredLength = 6;
                    options.Password.RequiredUniqueChars = 2;
                    options.Password.RequireNonAlphanumeric = false;
                })
                    .AddEntityFrameworkStores<ApplicationDbContext>()
                    .AddDefaultTokenProviders();
                #endregion



                #region Identity Server Configuration
                var assemblyName = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
                var builder = services.AddIdentityServer(options =>
                {
                    options.Events.RaiseErrorEvents = true;
                    options.Events.RaiseInformationEvents = true;
                    options.Events.RaiseFailureEvents = true;
                    options.Events.RaiseSuccessEvents = true;
                    options.EmitStaticAudienceClaim = true;

                })
                    .AddConfigurationStore(opts => 
                    {
                        opts.ConfigureDbContext = c => c.UseSqlServer(Configuration.GetConnectionString("IdentityServerDbConnection"), sqlOptions => sqlOptions.MigrationsAssembly(assemblyName));
                    })
                    .AddOperationalStore(opts => (refresh token, authorization code)
                    {
                        opts.ConfigureDbContext = c => c.UseSqlServer(Configuration.GetConnectionString("IdentityServerDbConnection"), sqlOptions => sqlOptions.MigrationsAssembly(assemblyName));
                    })
                    .AddDeveloperSigningCredential()
                    .AddAspNetIdentity<ApplicationUser>()
                    .AddResourceOwnerValidator<IdentityResourceOwnerPasswordValidator>();
                #endregion
                services.AddAuthentication()
                    .AddGoogle(options =>
                    {
                        options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                        options.ClientId = "DynamicBoxWorkflow";
                        options.ClientSecret = "secret";
                    });
                builder.AddDeveloperSigningCredential();
            }
            public void Configure(IApplicationBuilder app)
            {
                if (Environment.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                    app.UseDatabaseErrorPage();
                }
                app.UseStaticFiles();
                app.UseRouting();
                app.UseIdentityServer();
                app.UseAuthorization();
                app.UseAuthentication();
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapDefaultControllerRoute();
                });
            }
        }
    }

enter image description here

enter image description here

I made a definition like this on the client API side. But the user does not have permission, but he can read even though he is not authorized.

Client API

    #region Identity Server 4 -> JWT Auth
    builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
    {
        options.Authority = builder.Configuration["IdentityServer:Authority"];
        options.Audience = "resource_purchasing";
        options.RequireHttpsMetadata = false;
    });
    #region Authorization - Claims
    builder.Services.AddAuthorization(opts =>
    {
        opts.AddPolicy("CreatePurchasingManagement", policy =>
        {
            policy.RequireClaim("scope", new[] { "purchasing.create" });
        });
        opts.AddPolicy("ReadPurchasingManagement", policy =>
        {
            policy.RequireClaim("scope", new[] { "purchasing.read" });
        });
        opts.AddPolicy("UpdatePurchasingManagement", policy =>
        {
            policy.RequireClaim("scope", new[] { "purchasing.update" });
        });
        opts.AddPolicy("DeletePurchasingManagement", policy =>
        {
            policy.RequireClaim("scope", new[] { "purchasing.delete" });
        });
    });
    #endregion


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source