从 3.1.4 更新身份服务器 4 4.0.0 后范围无效 asp.net 核心 3 与 Mongo 数据库

After updating the identity server 4 4.0.0 from 3.1.4 Scope is invalid asp.net core 3 with Mongo DB

在发现文档中,未添加范围IdentityPortal.API

{
    "issuer": "https://localhost:5001",
    "scopes_supported": ["profile", "openid", "email", "offline_access"],   
}

但是,配置中允许的范围如下

private static string apiScope = "IdentityPortal.API";
private static ICollection<string> AllowedScopes()
        {
            return new List<string>
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Email,
                apiScope
            };
        }

API资源

   public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource(apiScope, "Falcon Api")
                {
                    Scopes = new List<string>{apiScope},
                    UserClaims =
                    {
                        JwtClaimTypes.Profile,
                        JwtClaimTypes.Name,
                        JwtClaimTypes.Email,
                    }
                }
            };
        }

我从 React 应用程序发送范围如下

 scope: "profile openid email IdentityPortal.API offline_access",

在身份服务器中 IdentityPortal.API 未添加为受支持的声明。

这里是customPersistedGrantStore.cs

public class CustomResourceStore : IResourceStore
{
    protected IRepository _dbRepository;

    public CustomResourceStore(IRepository repository)
    {
        _dbRepository = repository;
    }


    public Task<IEnumerable<IdentityResource>> FindIdentityResourcesByScopeNameAsync(IEnumerable<string> scopeNames)
    {
        var list = _dbRepository.Where<IdentityResource>(e => scopeNames.Contains(e.Name));
        return Task.FromResult(list.AsEnumerable());
    }

    public Task<IEnumerable<ApiScope>> FindApiScopesByNameAsync(IEnumerable<string> scopeNames)
    {
        var list = _dbRepository.Where<ApiScope>(a => scopeNames.Contains(a.Name));
        return Task.FromResult(list.AsEnumerable());
    }

    public Task<IEnumerable<ApiResource>> FindApiResourcesByScopeNameAsync(IEnumerable<string> scopeNames)
    {
        var list = _dbRepository.Where<ApiResource>(a => a.Scopes.Any(s => scopeNames.Contains(s)));
        return Task.FromResult(list.AsEnumerable());
    }

    public Task<IEnumerable<ApiResource>> FindApiResourcesByNameAsync(IEnumerable<string> apiResourceNames)
    {
        var list = _dbRepository.Where<ApiResource>(a => apiResourceNames.Contains(a.Name));
        return Task.FromResult(list.AsEnumerable());
    }

    public Task<Resources> GetAllResourcesAsync()
    {
        var result = new Resources(GetAllIdentityResources(), GetAllApiResources(),null);
        return Task.FromResult(result);
    }
    
    private IEnumerable<IdentityResource> GetAllIdentityResources()
    {
        return _dbRepository.All<IdentityResource>();
    }
    private IEnumerable<ApiResource> GetAllApiResources()
    {
        return _dbRepository.All<ApiResource>();
    }
    private IEnumerable<ApiScope> GetAllApiScopes()
    {
        return _dbRepository.All<ApiScope>();
    }
}

身份服务器设置

services.Configure<MongoDbConfigurationOptionsViewModel>(Configuration);
        services.AddIdentityServer()//.AddProfileService<ProfileService>()
            .AddMongoRepository()
            .AddMongoDbForAspIdentity<ApplicationUser, IdentityRole>(Configuration)
            .AddClients()
            .AddInMemoryApiScopes(Config.AllowedScopes())
            .AddIdentityApiResources()
            .AddPersistedGrants()
            .AddDeveloperSigningCredential();
        
        services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
            .AddIdentityServerAuthentication(options =>
            {
                // base-address of your identityserver
                options.Authority = "https://localhost:5001";

                // name of the API resource
                options.ApiName = "IdentityPortal.API";
            });

配置

 public static IEnumerable<ApiScope> AllowedScopes()
        {
            return new List<ApiScope>
            {
                new ApiScope(IdentityServerConstants.StandardScopes.OpenId),
                new ApiScope(IdentityServerConstants.StandardScopes.Profile),
                new ApiScope(IdentityServerConstants.StandardScopes.Email),
                new ApiScope(apiScope)
            };
        }

问题是您刚刚在 IDS4 设置中添加了 api 资源,您需要更改代码以添加 API 范围。要添加上面的 api 个范围,您可以通过 AddInMemoryApiScopes 添加它。代码如下:

services.Configure<MongoDbConfigurationOptionsViewModel>(Configuration);
            services.AddIdentityServer()//.AddProfileService<ProfileService>()
                .AddMongoRepository()
                .AddMongoDbForAspIdentity<ApplicationUser, IdentityRole>(Configuration)
                .AddClients()
                .AddInMemoryApiScopes(Config.AllowedScopes)
                .AddIdentityApiResources()
                .AddPersistedGrants()
                .AddDeveloperSigningCredential();
            

更改代码后,重新生成令牌并在 https://jwt.ms/ 上检查它,您应该有一个 aud = IdentityPortal.API 的道具和 IdentityPortal.API

的范围

当你使用数据库时,你需要先将你的数据库迁移到新版本,这里有一些脚本可以帮助解决这个问题:https://github.com/RockSolidKnowledge/IdentityServer4.Migration.Scripts/tree/CreateScripts 数据库更新后,确保您在 api 资源上有数据,并且 api 资源的范围与所需的范围相匹配

查看我的博客 post https://github.com/nahidf-adventures/IdentityServer4-adventures/tree/ids4-4/src/IdentityServer 以获得更详细的解释。 阅读更多官方文档 here