2017-02-12 81 views
1

我想使用OpenIddict實現OpenIdConnect/Oauth2服務器以保護.NET核心API應用程序。我見過的大多數例子都將這些作爲單獨的項目實現OpenIddict - 在同一個項目中託管auth服務器和web api資源

客戶端應用程序是一個SPA,我們正在使用隱式流。

我已經根據我對OpenIddict樣品在這裏顯示的代碼解決方案: https://github.com/openiddict/openiddict-samples

對於我這個工作,該項目將有理想的驗證服務器和API來使用相同的端口,並在同一個項目。 (客戶的其中一個要求是他們不希望另一個服務器配置,因爲他們擁有API資源並且它將位於同一服務器上)

我配置了OpenIddict並將其與我們的API項目相結合。幾乎所有功能都能正常工作 - API端點受到[Authorize]屬性的保護,並阻止訪問受保護的API端點。但是,當API資源受到保護時,返回結果是Auth服務器本身的HTML登錄頁面,而不是返回401 Unauthorized HTTP狀態碼。

這裏是我的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();出現兩次在您的管道,這違背了在app.UseWhen()分支建設者使用branch.UseIdentity()的整個目的(即製作確保不會爲您的API端點調用通過Identity註冊的Cookie中間件)。

刪除第一次出現,它應該工作。

+1

謝謝!這就是問題 - 現在就像一個魅力:) – user1750537

0

您將AutomaticChallenge設置爲true。根據documentation

該標誌表示當授權失敗時,該中間件應該將瀏覽器重定向到LoginPath或AccessDeniedPath。

所以通過設置爲false,它不會重定向到登錄。

相關問題