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