Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constantly get invalid scope error after udating my identityserver4

I had identityProviderService working with my API and web app, then I updated i updated my dependecies(identityServer4) and that resulted constantly in the following error either I use code or I hybrid.

IdentityServer4 Error: Invalid_scope

I checked the log and the scope was fine but I can resolve why I keep getting this error! The details as follows:

My local Idp (Identityserver4) log and the main error =>

IdentityServer4.Hosting.IdentityServerMiddleware: Information:
Invoking IdentityServer endpoint:
IdentityServer4.Endpoints.AuthorizeEndpoint for /connect/authorize
IdentityServer4.Validation.DefaultResourceValidator: Error: Scope
Bd.Web.Api not found in store.
IdentityServer4.Endpoints.AuthorizeEndpoint: Error: Request validation
failed IdentityServer4.Endpoints.AuthorizeEndpoint: Information: {  
"ClientId": "BdWebAppClientId",   "ClientName": "Bd web Client
Application",   "RedirectUri": "https://localhost:xxxxx/signin-oidc", 
"AllowedRedirectUris": [
    "https://localhost:44386/signin-oidc"   ],   "SubjectId": "anonymous",   "ResponseType": "code",   "ResponseMode": "form_post", 
"GrantType": "authorization_code",   "RequestedScopes": "openid
profile Bd.Web.Api",   "State":
"CfDJ8Foioa24zShFmzIFmkTbGBTrbiiEwQYmHGMRUN7FwsfKMgY2-olWJA1XVlAkA0uCWIR6HhMdu2X1exzVKTNFTcAD456Z0r3es5ki377uBEJgjA9jmyQFWWzTZV6_7GEmIC39xUh_b_YAqXgtzO0olZ52beNFuxruk_NshL47NhwcaETCH2cy3XTvRN0NTxZHmxVWglo13iSE7RVpNghHc7pBW7jCv7cB2RldQnEvsJ4s56AdiICw9sdKEJ5mQNoXngshanycX4MmD3qaW0TX6knY43pAqMuPgEEVqd7BXKt_koQfiQuAP3pQNbsyOAb1jtoZ8egUHiKgXjofs8ci2i4",
"PromptMode": "",   "Raw": {
    "client_id": "BdWebAppClientId",
    "redirect_uri": "https://localhost:xxxxx/signin-oidc",
    "response_type": "code",
    "scope": "openid profile Bd.Web.Api",
    "response_mode": "form_post",
    "nonce": "637284460180108591.ZjIxYjhlZGEtYjk0Mi00M2UxLWExNWItOGYzMjhjODEyMGQzZmU5NjZmZDAtOTQwYi00YTFlLWJlMWUtM2U3YzBhM2NmNjQ4",
    "state": "CfDJ8Foioa24zShFmzIFmkTbGBTrbiiEwQYmHGMRUN7FwsfKMgY2-olWJA1XVlAkA0uCWIR6HhMdu2X1exzVKTNFTcAD456Z0r3es5ki377uBEJgjA9jmyQFWWzTZV6_7GEmIC39xUh_b_YAqXgtzO0olZ52beNFuxruk_NshL47NhwcaETCH2cy3XTvRN0NTxZHmxVWglo13iSE7RVpNghHc7pBW7jCv7cB2RldQnEvsJ4s56AdiICw9sdKEJ5mQNoXngshanycX4MmD3qaW0TX6knY43pAqMuPgEEVqd7BXKt_koQfiQuAP3pQNbsyOAb1jtoZ8egUHiKgXjofs8ci2i4",
    "x-client-SKU": "ID_NETSTANDARD2_0",
    "x-client-ver": "5.5.0.0"   }

My config comprises of three classes User, Resources and Client as follows:

public class Users
{
    public static List<TestUser> Get()
    {
        return new List<TestUser> {
            new TestUser {
                SubjectId = "5BE86359-073C-434B-AD2D-A3932222DABE",
                Username = "scott",
                Password = "password",
                Claims = new List<Claim> {
                    new Claim(JwtClaimTypes.Email, "[email protected]"),
                    new Claim(JwtClaimTypes.Role, "admin")
                }
            }
        };
    }
}


public class Resources
{
    public static  IEnumerable<IdentityResource> Ids()
    {
        return new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile(),
            new IdentityResources.Address()
        };
    }


    public static IEnumerable<ApiResource> Apis()
    {
        return new List<ApiResource>
        {
            new ApiResource("Bd.Web.Api", "Bd Web Api") {
                Description = "BD API Access",
                //UserClaims = new List<string> {"role"},
                ApiSecrets = new List<Secret> {new Secret("secret".Sha256())}
            }
        };
    }

}


public class Clients
{
    public static IEnumerable<Client> Get()
    {
        return new List<Client> {
            new Client {
                ClientId = "BdWebAppClientId",
                ClientName = "Bd web Client Application",
                AllowedGrantTypes = GrantTypes.Code,
                RequirePkce = false,
                ClientSecrets = new List<Secret> {
                    new Secret("secret".Sha256())},
                AllowedScopes = 
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    IdentityServerConstants.StandardScopes.Address,
                    "Bd.Web.Api"
                },
                RedirectUris =  new List<string>{"https://localhost:44386/signin-oidc"},
                PostLogoutRedirectUris = new List<string>{ "https://localhost:44386/sigout-callback-oidc" }
            
            }

        };
    }
}


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.AddControllersWithViews();

        services.AddIdentityServer()
            .AddInMemoryClients(Clients.Get())
            .AddInMemoryIdentityResources(Resources.Ids())
            .AddInMemoryApiResources(Resources.Apis())
            .AddTestUsers(Users.Get())
            .AddDeveloperSigningCredential();
    }

    // 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.UseRouting();

        app.UseIdentityServer();

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

My web app startup as follows:

 public class Startup
 {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
        }

        public IConfiguration Configuration { get; }

            services.Configure<CookiePolicyOptions>(options =>
            {

                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.None;
            });
            

            services.AddMvc(options => { options.EnableEndpointRouting = false; }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            JsonConvert.DefaultSettings = () => new JsonSerializerSettings
            {
                Formatting = Formatting.Indented,
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            };

            services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

            services.AddHttpContextAccessor();

            services.AddTransient<BearerTokenHandler>();

            services.AddHttpClient("ApiClient", client =>
            {
                //client.BaseAddress = new Uri("https://bandapi.azurewebsites.net/api/");
                client.BaseAddress = new Uri("https://localhost:44301/api/");
                //client.BaseAddress = new Uri("https://192.168.1.25:44301/api/");
                client.Timeout = new TimeSpan(0, 0, 30);
                client.DefaultRequestHeaders.Clear();
                client.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/json");
                
               

            }).AddHttpMessageHandler<BearerTokenHandler>();

            services.AddHttpClient("IdpClient", client =>
            {

                client.BaseAddress = new Uri("https://localhost:xxxxx/");
                client.Timeout = new TimeSpan(0, 0, 30);
                client.DefaultRequestHeaders.Clear();
                client.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/json");
            }).AddHttpMessageHandler<BearerTokenHandler>();

            services.AddAuthentication(options =>
            {
                options.DefaultScheme = "BdWebAppCookies";
                options.DefaultChallengeScheme = "oidc";


                //options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                //options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
         .AddCookie("BdWebAppCookies"  /*CookieAuthenticationDefaults.AuthenticationScheme*/, options =>
         {
             options.AccessDeniedPath = "/Authentication/AccessDenied";
         })
         .AddOpenIdConnect("oidc" /*OpenIdConnectDefaults.AuthenticationScheme*/, options =>
         {

             options.Authority = "https://localhost:xxxx/";
             //options.RequireHttpsMetadata = true;
             options.ClientId = "BdWebAppClientId";

             
             options.Scope.Add("openid");
             options.Scope.Add("profile");
             options.Scope.Add("address");

             options.Scope.Add("Bd.Web.Api");

             
             options.ClientSecret = "secret";
             options.ResponseType = "code";
             options.UsePkce = false;
             options.SignInScheme = "BdWebAppCookies";
            
        }
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();
            app.UseCookiePolicy();

            app.UseAuthentication();
            app.UseAuthorization();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
   }
like image 572
Fallah Avatar asked Jun 22 '20 18:06

Fallah


People also ask

What does error invalid scope mean?

Invalid Scope – 400 errorYou probably created the project using a free Google account (or free educational/non-profit G Suite) rather than a paid G Suite (Google Apps) account.

What is scope in IdentityServer4?

Scope. Scopes are identifiers for resources that a client wants to access. This identifier is sent to the OP during an authentication or token request. By default every client is allowed to request tokens for every scope, but you can restrict that.

Is IdentityServer4 open source?

About IdentityServer4IdentityServer is a free, open source OpenID Connect and OAuth 2.0 framework for ASP.NET Core.


1 Answers

In IdentityServer4 4.x the handling of api scopes was changed. Now you need to define all available api scopes and provide them to the configuration.

The updated documentation shows how it's done. https://identityserver4.readthedocs.io/en/latest/topics/resources.html#scopes

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

Then add the scopes to your IdentityServer configuration:

    services.AddIdentityServer()
        .AddInMemoryApiScopes(Config.GetApiScopes());

Furthermore you need to add the scopes to your already defined ApiResources as described here: https://identityserver4.readthedocs.io/en/latest/topics/resources.html#api-resources

public static readonly IEnumerable<ApiResource> GetApiResources()
{
    return new List<ApiResource>
    {
        new ApiResource("invoices", "Invoice API")
        {
            Scopes = { "invoice.read", "invoice.pay", "manage" }
        },

        new ApiResource("customers", "Customer API")
        {
            Scopes = { "customer.read", "customer.contact", "manage" }
        }
    };
}
like image 94
crazy Avatar answered Oct 28 '22 20:10

crazy