identityserver4 добавляет ресурс api, вызывающий несанкционированные запросы

#angular #asp.net-core #identityserver4 #oidc-client-js

#angular #asp.net-ядро #identityserver4 #oidc-client-js

Вопрос:

У меня есть приложение, которое использует IdentityServer4 для аутентификации и Angular10 (с oidc-client-js) для интерфейса и ASP.NET Core API как ресурсный API. все работало нормально, пока я не добавил следующую строку в конфигурацию запуска API, затем после входа в систему все мои запросы возвращали 401.

  services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = Configuration.GetSection("ApplicationSettings").GetValue<string>("Authority");
         1-->   options.ApiName = "app-api";
         2-->   options.RequireHttpsMetadata = false;
         3-->   //options.ApiSecret = "apisecret";
        });
  

и в конфигурации IdSrv я добавил

   public static IEnumerable<ApiResource> Apis =>
        new ApiResource[]
        {
       4-->     new ApiResource("app-api", "Application Secured API")
            {
                ApiSecrets = { new Secret("apisecret".Sha256()) }
            }
        };

    public static IEnumerable<ApiScope> ApiScopes =>
        new ApiScope[]
    5-->      { new ApiScope("app-api") }; 

  public static IEnumerable<Client> Clients =>
        new Client[]
        {
            new Client {
                ClientName="Test App",
                ClientId="client-spa",
                AllowedGrantTypes = GrantTypes.Code,
                AlwaysIncludeUserClaimsInIdToken = true,
                RedirectUris = new List<string>() { "https://localhost:44383/signin-callback" , "https://localhost:44383/assets/silent-callback.html"}, 
                PostLogoutRedirectUris = {"https://localhost:44383/signout-callback" },
                AllowedCorsOrigins = { "https://localhost:44383" },
                AccessTokenLifetime = 60*5,
                AllowedScopes = {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
             6-->       "app-api"
                },
                RequireClientSecret=false
            }
        };
  

Запуск клиента

  public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);

        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist/ClientApp";
        });

        services.AddDbContext<MasterDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("PortalMaster")));
        services.AddDbContext<LocalDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("PortalLocal")));
        services.AddDbContext<PropelIdentityContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Identity")));

        services.AddCors(options =>
        {
            options.AddPolicy("AllRequests", builder =>
            {
                builder.AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowAnyOrigin();
            });
        });

        services.AddControllers(options => options.Filters.Add(new PortalHttpResponseExceptionFilter()));
        services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
        // configure Identity Server
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = "https://localhost:5001/";
            options.ApiName = "app-api";
        });
        
        //Register the Permission policy handlers
        services.AddSingleton<IAuthorizationPolicyProvider, AuthorizationPolicyProvider>();
        services.AddSingleton<IAuthorizationHandler, PermissionHandler>();

    }

  public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();

        app.UseStaticFiles();
        if (!env.IsDevelopment())
            app.UseSpaStaticFiles();

        app.UseCors("AllRequests");

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller}/{action=Index}/{id?}");
        });

        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });
    }
  

Запуск IdSrv

  public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        //Connection String 
        string connectionString = Configuration.GetConnectionString("Identity");
        services.AddDbContext<AppIdentityContext>(options => options.UseSqlServer(connectionString));


        //AspNetIdentity Configuration 
        services.AddIdentity<AppUser, IdentityRole>(options =>
        {
            options.User.RequireUniqueEmail = false;
            options.Lockout.MaxFailedAccessAttempts = Configuration.GetSection("AppSettings").GetValue<Int32>("MaxFailedAccessAttempts");

            //options.SignIn.RequireConfirmedEmail = true;
            //options.Password.RequiredLength = 8;
            //options.Password.RequireDigit = true;
            //options.Password.RequireUppercase = true;
            //options.Password.RequireLowercase = true;
            //options.Password.RequireNonAlphanumeric = true; 
        })
          .AddUserManager<AppUserManager>()
          .AddEntityFrameworkStores<AppIdentityContext>()
          .AddDefaultTokenProviders();
        //IdentityServer Configuration 
        var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

        var builder = services.AddIdentityServer(options =>
        {
            options.Events.RaiseErrorEvents = true;
            options.Events.RaiseInformationEvents = true;
            options.Events.RaiseFailureEvents = true;
            options.Events.RaiseSuccessEvents = true;
            options.UserInteraction.LoginUrl = "/Account/Login";
            options.UserInteraction.LogoutUrl = "/Account/Logout";
            options.Authentication.CookieLifetime = TimeSpan.FromMinutes(15);
        }).AddAspNetIdentity<PropelUser>()
        .AddProfileService<ProfileService>()
        .AddConfigurationStore(options =>
        {
            options.ConfigureDbContext = b => b.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly));
        })
        .AddOperationalStore(options =>
        {
            options.ConfigureDbContext = b => b.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly));
            options.EnableTokenCleanup = true;
        });

        //CORS configuration
        services.AddCors(options =>
        {
            options.AddPolicy("AllowAllOrigins", builder =>
            {
                builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();

            });
        });


        //Signing Credentials. Reading from tempkey saved on project for development, and from SSL certificate on Release
        if (Environment.IsDevelopment())
        {
            builder.AddDeveloperSigningCredential();

        }
        else
        {
            builder.AddSigningCredential(LoadCertificateFromStore());
        }



    }
  

Мой вопрос в том, каков риск, если я удалю часть ApiResource (все отмеченные строки от 1 до 6)? и как я могу решить проблему, если я должен их сохранить?

Ответ №1:

Лучше всего хранить ваш IdentityServer в отдельной службе, просто чтобы вы могли рассуждать о том, как все это работает. Когда это одно место, очень сложно понять, что происходит. Я бы начал с отдельного IdentityServer, а затем объединил, когда он заработает и когда вы полностью поймете, что происходит.

Если вы получаете исключение «Вы должны либо установить полномочия, либо IntrospectionEndpoint» в вашем API, значит, полномочия установлены неправильно. У вас есть исходный код для исключения здесь.

При запуске вашего Api я бы также установил схему аутентификации по умолчанию на:

Услуги.Добавление аутентификации (JwtBearerDefaults.Схема аутентификации)

Смотрите эту страницу:

Комментарии:

1. нет, это все то же самое, и когда я проверяю журналы, у меня возникает эта ошибка IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler You must either set Authority or IntrospectionEndpoint System.InvalidOperationException: You must either set Authority or IntrospectionEndpoint

2. Как выглядит ваш класс запуска в вашем клиентском приложении? Кроме того, вы уверены, что эта конфигурация действительно установлена? Опции. Полномочия = конфигурация. GetSection(«ApplicationSettings»)

3. Я обновил сообщение и добавил запуск клиента. Я уверен, что варианты. Полномочия установлены правильно

4. я переписал свой ответ.

5. Извините, я должен был добавить все с самого начала. У меня есть отдельный проект для identityserver и один для API. Я включил свой запуск для identityserver. Я неправильно настраиваю конфигурацию?