2017-02-12 45 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,它不会重定向到登录。

相关问题