使用 WsFederation 的授权属性从不执行带注释的控制器操作

Authorize attribute using WsFederation never executes annotated controller action

我正在使用 WsFederation 中间件访问 ADFS 服务器进行身份验证。 ADFS 被赋予一个特定的端点以在中间件和 ADFS 之间的对话结束时回调。如果我没有在我的代码中提供一个实际的端点(一些响应 route = callback 端点的动作),我会得到一个 404。如果我在那个端点实现了一个动作,我没有得到任何有用的东西(例如 'User' 未设置)和 - 无论我在响应结束时做什么,都会直接返回到用户的浏览器。我用 [Authorize] 装饰的动作在任何时候都没有执行。


From startup:

   public void ConfigureServices(IServiceCollection services)
    {         
        services.AddControllersWithViews();

        // set up ADFS authentication
        services.AddAuthentication(sharedOptions => {
            sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
        }).AddWsFederation(options =>
        {
            options.MetadataAddress = "<adfs-server>/FederationMetadata/2007-06/FederationMetadata.xml";
            options.Wtrealm = "<my-apps-server>/authviaadfs/auth-callback";
        }).AddCookie("Cookies", o => { });
        
        // set up custom authorization
        services.AddAuthorization(options => { });
        services.AddControllersWithViews();
        services.AddRazorPages();
    }
  
   public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            //app.UseHsts();
        }
        app.UseStaticFiles();

        app.UseRouting();

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

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

From MyController:

[Authorize]
public IActionResult MyProtectedPage()
{
    ... code that never, ever, executes when decorated with [Authorize]
}

[Route("/authviaadfs/auth-callback")]
public IActionResult AuthCallback()
{
    ... code that executes after I log in via ADFS 
    ... response that returns to the original caller of "MyProtectedPage"
}

谁能告诉我我做错了什么?我遵循了六个不同的 Google 搜索网站的方法,这些网站说“这就是您向 ADFS 进行身份验证的方式”(所有内容略有不同,但要点是相同的,包括仅设置 'MetadataAddress' 和 [= 的选项19=]).

好吧,我明白了 - “在现实世界中无用的 Google 示例”和“bad/missing 如何做某事的文档”的另一个示例。

如果您想使用“/”以外的端点,除了“MetadataAddress”和“Wtrealm”之外,还有另一个“选项”需要设置 - 一个名为“CallbackPath”的选项。这告诉中间件你的代码中的什么路由“吞并处理”;如果你不设置它(因为我最初没有,按照食谱)那么你的中间件不知道要拦截哪个请求。因此,就我在问题中提供的示例代码而言,在设置 options.MetadataAddress 和 options.Wtrealm 之后,您将设置以下内容:


options.CallbackPath = "/authviaadfs/auth-callback";

这告诉中间件在请求管道内拦截对“/authviaadfs/auth-callback”的任何调用,并使用请求和 headers 完成身份验证,然后有效地将控制权交给您受保护的控制器操作。中间件创建一个关联 cookie,它随第一次重定向一起发送到您的 ADFS 服务器,然后在“/authviaadfs/auth-callback”中使用该 cookie 将来自 ADFS 的 return 调用与正确的请求上下文相匹配正在认证中。