mohammadmahdi Talachi
mohammadmahdi Talachi

Reputation: 601

Identityserver4 not authorized api in blazor client

I use identity server 4 with blazor server side client

everything is ok but token not authorized api methods but token works in server authorized controllers

is something wrong with grant type or code flow ?

server config class :

 public static class Configurations
    {
        public static IEnumerable<IdentityResource> GetIdentityResources() =>
            new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
            };

        public static IEnumerable<ApiResource> GetApis() =>
            new List<ApiResource> {
                new ApiResource("api1")
            };

        public static IEnumerable<ApiScope> GetApiScopes()
        {
            return new List<ApiScope>
            {
                // backward compat
                new ApiScope("api1")
            };
        }

        public static IEnumerable<Client> GetClients() => new List<Client>
        {
        new Client
            {
                ClientId = "client",
                AllowedGrantTypes = GrantTypes.Code,
                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },
                AllowedScopes = { 
                        "api1" ,
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                },
                RedirectUris = { "https://localhost:44372/signin-oidc" },

                AlwaysIncludeUserClaimsInIdToken = true,

                AllowOfflineAccess = true,
                RequireConsent = false,
                RequirePkce = true,
            }
        };

     
    }

server start up class :

  public void ConfigureServices(IServiceCollection services)
        {

            services.AddDbContext<AppDbContext>(config =>
            {
                config.UseInMemoryDatabase("Memory");
            });

            // AddIdentity registers the services
            services.AddIdentity<IdentityUser, IdentityRole>(config =>
            {
                config.Password.RequiredLength = 4;
                config.Password.RequireDigit = false;
                config.Password.RequireNonAlphanumeric = false;
                config.Password.RequireUppercase = false;
            })
                .AddEntityFrameworkStores<AppDbContext>()
                .AddDefaultTokenProviders();

            services.ConfigureApplicationCookie(config =>
            {
                config.Cookie.Name = "IdentityServer.Cookie";
                config.LoginPath = "/Auth/Login";
                config.LogoutPath = "/Auth/Logout";
            });



            services.AddIdentityServer()
                .AddAspNetIdentity<IdentityUser>()
               //.AddInMemoryApiResources(Configurations.GetApis())
               .AddInMemoryIdentityResources(Configurations.GetIdentityResources())
               .AddInMemoryApiScopes(Configurations.GetApiScopes())
               .AddInMemoryClients(Configurations.GetClients())
               .AddDeveloperSigningCredential();

            services.AddControllersWithViews();
        }

api start up class :

            services.AddAuthentication("Bearer").AddIdentityServerAuthentication(option =>
            {
                option.Authority = "https://localhost:44313";
                option.RequireHttpsMetadata = false;
                option.ApiName = "api1";
            });

blazor server side start up class:

services.AddAuthentication(config =>
            {
                config.DefaultScheme = "Cookie";
                config.DefaultChallengeScheme = "oidc";
            })
                .AddCookie("Cookie")
                .AddOpenIdConnect("oidc", config =>
                {
                    config.Authority = "https://localhost:44313/";
                    config.ClientId = "client";
                    config.ClientSecret = "secret";
                    config.SaveTokens = true;
                    config.ResponseType = "code";
                    config.SignedOutCallbackPath = "/";
                    config.Scope.Add("openid");
                    config.Scope.Add("api1");
                    config.Scope.Add("offline_access");
                });

            services.AddMvcCore(options =>
            {
                var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser() // site-wide auth
                    .Build();
                options.Filters.Add(new AuthorizeFilter(policy));
            });

Upvotes: 0

Views: 445

Answers (2)

nahidf
nahidf

Reputation: 2394

To fix this issue, you have 2 options:

1- (Recommended) To add the scopes to API resource like this:

public static IEnumerable<ApiResource> GetApis() =>
            new List<ApiResource> {
                new ApiResource("api1")
                {
                    Scopes = new []{ "api1" }
                }
            };

        public static IEnumerable<ApiScope> GetApiScopes()
        {
            return new List<ApiScope>
            {
                // backward compat
                new ApiScope("api1")
            };
        }

2- On API change your code to set ValidateAudience = false, like this:

services.AddAuthentication("Bearer").AddJwtBearer("Bearer",
   options =>
   {
      options.Authority = "http://localhost:5000";
      options.Audience = "api1";
      options.RequireHttpsMetadata = false;
      options.TokenValidationParameters = new 
         TokenValidationParameters()
         {
            ValidateAudience = false
         };
   });

Here is my blog about migrating IdentityServer4 to v4 https://nahidfa.com/posts/migrating-identityserver4-to-v4/

Upvotes: 1

Umair
Umair

Reputation: 5461

I have not actually used AddIdentityServerAuthentication in API but can you try the below code. Technically its same thing, but maybe this will work.

Change your api authentication from AddIdentityServerAuthentication to AddJwtBearer:

   services.AddAuthentication("Bearer").AddIdentityServerAuthentication(option =>
            {
                option.Authority = "https://localhost:44313";
                option.RequireHttpsMetadata = false;
                option.ApiName = "api1";
            });

to

   services.AddAuthentication("Bearer")
           .AddJwtBearer("Bearer", option =>
           {
               option.Authority = "https://localhost:44313";
               option.Audience = "api1";
               option.SaveToken = true;
           });

Upvotes: 0

Related Questions