3

In the discovery document, the scope IdentityPortal.API is not added

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

However, allowed scope in the config is as below

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 Resource

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

From the React Application I am sending scope as below

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

In the identity server IdentityPortal.API is not added as supported claim.

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

Identity server setup

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

Config

 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)
            };
        }
San Jaisy
  • 15,327
  • 34
  • 171
  • 290
  • 1
    The new version has some [rework on scopes](https://leastprivilege.com/2020/06/18/resource-access-in-identityserver4-v4-and-going-forward/), check the [release notes](https://github.com/IdentityServer/IdentityServer4/releases/tag/4.0.0). Your issue may be similar to [this one](https://stackoverflow.com/questions/62543026/identity-server-invalid-scope-in-example-from-the-documentation-with-version-4-0). –  Jun 29 '20 at 14:32
  • can you post your identityserver setup? – nahidf Jun 30 '20 at 20:15
  • @nahidf Added the setup code for Identity Server – San Jaisy Jul 01 '20 at 03:21

1 Answers1

4

Issue is that you just added the api resources on IDS4 setup, you need to change your code to add API scopes too. To add api scopes you have above you can add it via AddInMemoryApiScopes. Code would like this:

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

Once made the code change, regenerate the token and check it on https://jwt.ms/ you should have a prop as aud = IdentityPortal.API and also scope as IdentityPortal.API

As you are using DB, you need to migrate your DB to new version first, here are scripts to help on this: https://github.com/RockSolidKnowledge/IdentityServer4.Migration.Scripts/tree/CreateScripts After DB update make sure you have data on api resource and also api resource's scope matching the required scopes

Checkout my blog post https://github.com/nahidf-adventures/IdentityServer4-adventures/tree/ids4-4/src/IdentityServer for more detailed explanation. Read more on official docs here

nahidf
  • 2,260
  • 1
  • 15
  • 22
  • No this didn't help I can see "scopes_supported": ["profile", "openid", "email", "offline_access"], in https://localhost:5001/.well-known/openid-configuration. It should contain IdentityPortal.API – San Jaisy Jul 03 '20 at 05:03
  • you mean even after adding `AddInMemoryApiScopes(Config.AllowedScopes)` its not in the list? sorry for re-confirm cause this is almost impossible to happen. I have a full sample here https://github.com/nahidf-adventures/IdentityServer4-adventures/tree/ids4-4/src/IdentityServer - Migrated to v4 earlier this week – nahidf Jul 03 '20 at 05:13
  • yes still I get the same, Updated the code please have a look – San Jaisy Jul 03 '20 at 05:31
  • I can't figure why this is happening, maybe share your repo link with me then I'll take a look. btw I blogged the migration process on https://nahidfa.com/posts/migrating-identityserver4-to-v4/ feel free to give it a read for deeper reasoning behind the changes – nahidf Jul 03 '20 at 19:48
  • I went through the post in the config for ApiScopes and ApiResources I can see you have added api1 and api2 in both the method. Do I need to add on both the method ? – San Jaisy Jul 04 '20 at 02:58
  • correct, in your case you need to add `IdentityPortal.API` as Api resource and also api scope – nahidf Jul 04 '20 at 03:08
  • I found the issue if I use .AddInMemoryApiScopes(Config.ApiScopes) .AddInMemoryApiResources(Config.ApiResources) then I can see the supported_scope. But I am using mongoDb with method .AddIdentityApiResources(); builder.Services.AddTransient(); how can I achieve with this. – San Jaisy Jul 04 '20 at 13:59
  • I see! what you need to do is to 1. migrate your DB to new version first, here are scripts to help on this https://github.com/RockSolidKnowledge/IdentityServer4.Migration.Scripts/tree/CreateScripts 2. make sure you have data on api resource and also api resource scripts matching the required scopes - I hope this helps – nahidf Jul 05 '20 at 17:17
  • @SanJaisy how did it go? – nahidf Jul 07 '20 at 12:10
  • @SanJaisy amazing happy to hear! – nahidf Jul 07 '20 at 13:28