IdentityServer4 always returning "error": "invalid_scope"

Viewed 8094

I'm using IdentityServer4(4.0.4), however it doesn't return the access_token, it always returns: "error": "invalid_scope"

The error can be recreated just by adding the following code and the Nuget packages IdentityServer4(4.0.4) and IdentityServer4.EntityFramework(4.0.4). Adding 'scope' in the request doesn't make any difference.

This is the endpoint being triggered from Postman:

enter image description here

This is my Config class:

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

namespace WebApplication1
{
    public class Config
    {
        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource("ApiName", "ApiDisplayName")
            };
        }

        public static List<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile() // <-- usefull
            };
        }

        public static IEnumerable<Client> GetClients()
        {
            return new[]
            {
                // for public api
                new Client
                {
                    ClientId = "secret_client_id",
                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                 AllowedScopes =
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    "ApiName"
                }
            }
        };
    }
}
}

This is my Startup class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace WebApplication1
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddIdentityServer()
             .AddDeveloperSigningCredential()
             .AddOperationalStore(options =>
             {
                 options.EnableTokenCleanup = true;
                 options.TokenCleanupInterval = 30; // interval in seconds
             })
             .AddInMemoryApiResources(Config.GetApiResources())
             .AddInMemoryClients(Config.GetClients())
             .AddInMemoryIdentityResources(Config.GetIdentityResources());
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseIdentityServer();
            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });
        }
    }
}

enter image description here

5 Answers

Double check that your client isn't looking at a scope that isn't configured in your ApiScopes configuration. In the example below, my client registration is looking at "THIS_IS_AN_INVALID_SCOPE", but I don't actually have this scope defined in my ApiScopes.

        public static class Scopes
        {
            public static IEnumerable<ApiScope> Get()
            {
                return new[]
                {
                    new ApiScope("ProtectedResource.Scope1", "Access to ProtectedResource.Scope1"),
                    new ApiScope("ProtectedResource.Scope2", "Access to ProtectedResource.Scope2")
                };
            }
        }
        public static class Clients
        {
            public static IEnumerable<Client> Get()
            {
                return new List<Client>
                {
                    new Client
                    {
                        ClientId = "IntegrationTests",
                        ClientName = "Example client application using client credentials",
                        AllowedGrantTypes = GrantTypes.ClientCredentials,
                        ClientSecrets = new List<Secret> {new Secret("not_the_actual_password".Sha256())},
                        AllowedScopes = new List<string> {"THIS_IS_AN_INVALID_SCOPE"},
                        AccessTokenLifetime = 300 //5 Minutes
                    },
                };
            }
        }
 

You have to add ApiScope in the config. was changed in the latest IdentityServer4 just like this:

        public static IEnumerable<ApiScope> GetApiScopes()
    {
        return new List<ApiScope>
             {
                 new ApiScope(name: "read",   displayName: "Read your data."),
                 new ApiScope(name: "write",  displayName: "Write your data."),
                 new ApiScope(name: "delete", displayName: "Delete your data."),
                 new ApiScope(name: "identityserverapi", displayName: "manage identityserver api endpoints.")
             };
    }

As mentioned by @DES PRO You need to add ApiScope in the config file as below.

    public static IEnumerable<ApiScope> GetApiScopes()
        {
            return new List<ApiScope>
             {
                 new ApiScope(name: "ApiOne")
             };
        }

Then you add the scope to the ConfigureService in Startup.cs class. this answers @raphael question "Where does the Scopes class being used?"

public void ConfigureServices(IServiceCollection services)
{
            services.AddIdentityServer()
                .AddInMemoryApiResources(Configuration.GetApis())
                .AddInMemoryClients(Configuration.GetClients())
                .AddInMemoryApiScopes(Configuration.GetApiScopes())
                .AddDeveloperSigningCredential();

            services.AddControllersWithViews();
}

You need to verify what do you have in the table ApiScopes.

Related