如何在 OWIN 应用程序中使用 cookie 身份验证和 WsFederation 身份验证

How to use cookie authentication with WsFederation authentication in OWIN app

我正在制作一个 OWIN 应用程序来自行托管网站。我在身份验证部分遇到问题。我正在寻找的基本流程是:

  1. 检查请求是否有正确的 cookie。如果它有正确的 cookie,则获取 SecuritySessionToken 并构建 ClaimsIdentity,然后 return AuthenticationTicket.
  2. 如果 cookie 不存在,请告知 STS。
  3. 从 STS 获取 SAML 令牌并构建声明和身份验证票证。 (虽然我用的是WsFederation认证,这里不涉及ADFS。)

第 1 步对我来说效果很好。第 2 步和第 3 步是我遇到问题的地方。

这是我在启动时的配置方法class:

public void Configuration(IAppBuilder app)
{
    CookieAuthenticationOptions options = new CookieAuthenticationOptions
    {
        AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType,
        CookieName = "MyCookieName",
        CookiePath = "/cookiePath",
        AuthenticationMode = AuthenticationMode.Active
    };
    // Not relevant how this module is made. It helps with
    SessionAuthenticationModule module = this.CreateModule();
    app.Use(typeof(MyCookieAuthenticationMiddleware), app, options, module);

    WsFederationConfiguration fedConfig = new WsFederationConfiguration();
    fedConfig.Issuer = "https://mySTS.com/NotRealUrl/";
    SecurityTokenHandlerCollection handlerCollection = new SecurityTokenHandlerCollection(new List<SecurityTokenHandler>() { new SamlSecurityTokenHandler() });
    WsFederationAuthenticationOptions wsFederationOptions = new WsFederationAuthenticationOptions
    {
        Configuration = fedConfig,
        Wtrealm = "http://localhost/MyApp/NotRealUrl",
        Wreply = "https://mySTS.com/NotRealUrl/Login",
        SecurityTokenHandlers = handlerCollection,
        AuthenticationMode = AuthenticationMode.Active,
        AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
    };
    app.Use(typeof(MyWsFederationAuthenticationMiddleware), app, wsFederationOptions);
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
    app.Use<MyMiddleware>();
}

app.Use(typeof(MyCookieAuthenticationMiddleware), app, options, module);之前的部分工作正常。也就是说,当 cookie 存在时,我使用自定义 cookie 身份验证中间件 (MyCookieAuthenticationMiddleware) 生成 AuthenticationTicket.

不起作用的部分是WsFederation身份验证中间件部分。我为此创建了自己的中间件 (MyWsFederationAuthenticationMiddleware),这样我就可以查看发生了什么,因为直接 app.UseWsFederationAuthentication(wsFederationOptions) 对我不起作用。我正在查看 WsFederationAuthenticationHandler.cs 的源代码来指导我,但我仍然对一些总体概念感到困惑。

问题

  1. 我想我知道一般流程应该是什么(我在 顶部),但我不确定这如何准确地转化为 中间件管道。如果我没有 cookie,那么我会发现这个 在 AuthenticateCoreAsync()MyCookieAuthenticationHandler。但 我什么时候将其重定向到 STS 以获取 SAML 令牌? 我是否只是等待管道达到 AuthenticateCoreAsync() MyWsFederationAuthenticationHandler,如果用户不是 通过身份验证,然后获取令牌?
  2. 我实际上如何告诉它需要获取令牌的管道 来自STS?再看看 WsFederationAuthenticationHandler.cs,好像他们的 ApplyResponseChallengeAsync() 的实施可能正在做 我想要的是?更具体地说,如果它是 401 状态代码,则 a WsFederationMessage 并使用该消息重定向到 STS?
  3. 假设我实际上可以将 STS 获取到 return 我想要的令牌, return 到管道的哪个位置?

感谢和抱歉这么长的 post。

更新 1

我忘了说,当我 运行 我的代码使用 app.UseWsFederationAuthentication(wsFederationOptions)(而不是我自己的 MyWsFederationAuthenticationMiddleware)时,我得到了 400 "bad request - request too long" 错误。 URL 很长,看起来包含各种查询参数,包括 wtrealm、wctx、wa 和 wreply,每个参数都包含 url 编码的字符串。看起来 wctx 真的很长。我想这是一些 base64 编码的对象。不幸的是我真的不知道发生了什么。

我认为,问题是,两个中间件都有 AuthenticationMode Active

您应该将 CookieAuthenticationOptions.AuthenticationType 更改为 CookieAuthenticationDefaults.AuthenticationType,然后将 WsFederationAuthenticationOptions.AuthenticationMode 设置为被动。

我推荐一个自定义控制器。如果用户访问此控制器,您必须为 WsFederationAuthenticationDefaults.AuthenticationType 和 return 和 401 手动触发 OwinContext.Authentication 上的身份验证。这应该触发 [=18= 中的 ApplyResponseChallengeAsync ]

WsFederationAuthenticationOptions.NotificationsSecurityTokenValidated 方法中,您可以使用 CookieAuthenticationDefaults.AuthenticationType 类型的身份发出新的 AuthTicket。

现在,来自身份提供者的身份已通过 cookieauth 转换为本地身份。