2017-02-12 13 views
1

Я хочу реализовать сервер OpenIdConnect/Oauth2 с использованием OpenIddict, чтобы защитить приложение API основного ядра .NET. Большинство примеров, которые я видел, реализуют их как отдельные проекты.OpenIddict - хостинг auth server и веб-ресурс api в том же проекте

Клиентское приложение - это SPA, и мы используем неявный поток.

Я основано мое решение на код, показанный в образцах OpenIddict здесь: https://github.com/openiddict/openiddict-samples

Для проекта я работаю над этим, в идеале иметь сервер идентификации и API, чтобы использовать один и тот же порт и быть в тот же проект. (Один из требований клиента заключается в том, что они не хотят, чтобы другой сервер настраивался, поскольку у них есть ресурс API, и он будет на одном сервере)

Я настроил OpenIddict и объединил его с нашим проектом API. Почти все работает правильно - конечные точки API защищены атрибутом [Authorize] и предотвращают доступ к защищенным конечным точкам API. Однако, когда ресурс API защищен, вместо того, чтобы возвращать 401 неавторизованный код статуса HTTP, возвращаемым результатом является страница входа в систему HTML самого сервера Auth.

Вот соответствующий код установки в моем файле Startup.cs:

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
    { 
     loggerFactory.AddConsole(Configuration.GetSection("Logging")); 
     loggerFactory.AddDebug(); 

     app.UseApplicationInsightsRequestTelemetry(); 

     if (env.IsDevelopment()) 
     { 
      app.UseDeveloperExceptionPage(); 
      app.UseDatabaseErrorPage(); 
      app.UseBrowserLink(); 
     } 
     else 
     { 
      app.UseExceptionHandler("/Home/Error"); 
     } 

     app.UseApplicationInsightsExceptionTelemetry(); 

     app.UseStaticFiles(); 

     app.UseIdentity(); 

     app.UseCors("AllowAll"); 
     //app.UseCors(builder => 
     //{ 
     // builder.AllowAnyOrigin();//)WithOrigins("http://localhost:9000"); 
     // builder.WithMethods("GET","POST", "PUT", "DELETE", "OPTIONS"); 
     // builder.WithHeaders("Authorization"); 
     //}); 

     app.UseWhen(context => !context.Request.Path.StartsWithSegments("/api"), branch => 
     { 
      branch.UseIdentity(); 
     }); 

     app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"), branch => 
     { 
      branch.UseOAuthValidation(); 

     }); 

     app.UseOpenIddict(); 


     #region Adding resource config here (api) 
     // Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715 

     app.UseOAuthIntrospection(options => 
     { 
      options.AutomaticAuthenticate = true; 
      options.AutomaticChallenge = true; 
      options.Authority = "http://localhost:5000"; 
      options.Audiences.Add("resource-server-1"); 
      options.ClientId = "resource-server-1"; 
      options.ClientSecret = "846B62D0-DEF9-4215-A99D-86E6B8DAB342"; 
     }); 

     //app.UseCors(builder => { 
     // builder.WithOrigins("http://localhost:9000"); 
     // builder.WithMethods("GET"); 
     // builder.WithHeaders("Authorization"); 
     //}); 
     #endregion 


     app.UseMvcWithDefaultRoute(); 

     // Seed the database with the sample applications. 
     // Note: in a real world application, this step should be part of a setup script. 
     InitializeAsync(app.ApplicationServices, CancellationToken.None).GetAwaiter().GetResult(); 

    } 

private async Task InitializeAsync(IServiceProvider services, CancellationToken cancellationToken) 
    { 
     // Create a new service scope to ensure the database context is correctly disposed when this methods returns. 
     using (var scope = services.GetRequiredService<IServiceScopeFactory>().CreateScope()) 
     { 
      var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>(); 
      //await context.Database.EnsureCreatedAsync(); 

      var manager = scope.ServiceProvider.GetRequiredService<OpenIddictApplicationManager<OpenIddictApplication>>(); 

      if (await manager.FindByClientIdAsync("MySPA", cancellationToken) == null) 
      { 
       var application = new OpenIddictApplication 
       { 
        ClientId = "MySPA", 
        DisplayName = "MySPA", 
        LogoutRedirectUri = "http://localhost:9000/signout-oidc", 
        RedirectUri = "http://localhost:9000/signin-oidc" 
       }; 

       await manager.CreateAsync(application, cancellationToken); 
      } 

      if (await manager.FindByClientIdAsync("resource-server-1", cancellationToken) == null) 
      { 
       var application = new OpenIddictApplication 
       { 
        ClientId = "resource-server-1" 
       }; 

       await manager.CreateAsync(application, "846B62D0-DEF9-4215-A99D-86E6B8DAB342", cancellationToken); 
      } 

     } 
    } 

Не уверен, как реализовать эти обе бок о бок в одном проекте. Как уже говорилось все это «работает», кроме API возвращает страницу HTML для входа и не нужный статус HTTP

ответ

1

app.UseIdentity(); присутствует дважды в вашем трубопроводе, который побеждает вся цель использования branch.UseIdentity() в app.UseWhen() разветвлений строитель (т.е. делает убедитесь, что промежуточное программное обеспечение cookie, зарегистрированное Identity, не вызывается для ваших конечных точек API).

Удалите первое возникновение, и оно должно работать.

+1

Спасибо! В этом была проблема - сейчас работает как шарм :) – user1750537

0

Вы устанавливаете AutomaticChallenge на true. Согласно documentation

этот флаг указывает на то, что промежуточное программное обеспечение должно перенаправить браузер на LoginPath или AccessDeniedPath при отказе авторизации.

Таким образом, установив это значение false, оно не будет перенаправлено на вход в систему.

 Смежные вопросы

  • Нет связанных вопросов^_^