【问题标题】:OWIN Challenge() method not executed when using multiple ADFS + Cookies使用多个 ADFS + Cookie 时未执行 OWIN Challenge() 方法
【发布时间】:2015-12-02 17:03:26
【问题描述】:

我的 ASP.Net 应用程序使用 OWIN/Katana/Claims,并允许使用以下方式登录:

  1. 传统用户名/密码(适用于所有用户)
  2. 谷歌
  3. Azure AD

它运行良好,所有必要的重定向/声明传输都运行良好(用户 NameIdentifier/Provider(/tenant) 详细信息被传回我的应用程序,因此可以链接唯一 id 值)。请注意,用户无需注册/注册该应用程序 - 访问权限由其组织的超级用户提供,并向他们发送用户名/密码,然后他们可以连接到 Google/Azure。

但是,我现在需要扩展此功能以允许用户连接到其组织的 ADFS 提供商。远程关闭的唯一有效示例是此处 (tutorial/code),但它严格基于 ADFS-only。当我将它应用到我的项目中时,它不起作用。

我的整个 StartupAuth 文件如下所示。我很感激可能存在配置错误,但根据我在过去六周中发现的样本碎片,这是我所拥有的最好的。

public void Configuration(IAppBuilder app)
    {
        // STANDARD CODE FOR APP COOKIE AND GOOGLE - WORKS PERFECTLY

        CookieAuthenticationOptions coa = new CookieAuthenticationOptions {
            AuthenticationMode = AuthenticationMode.Active,
            CookieName = "MyAppName",
            ExpireTimeSpan = TimeSpan.FromMinutes(60),
            SlidingExpiration = true,
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/login.aspx"),
            CookieHttpOnly = true,
            CookieSecure = CookieSecureOption.SameAsRequest,
            Provider = new CookieAuthenticationProvider { OnValidateIdentity = context =>
            {
                dynamic ret = Task.Run(() =>
                {
                    // Verify that "userId" and "customerId" claims exist, and that each has a valid value (greater than zero) - removed for brevity
                    return Task.FromResult(0);
                });
                return ret;
            } }
        };
        app.SetDefaultSignInAsAuthenticationType(coa.AuthenticationType);
        app.UseCookieAuthentication(coa);

        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
        app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions {
            ClientId = "84***********************k3.apps.googleusercontent.com",
            ClientSecret = "jue*****************Ppi"
        });



        // NEW CODE THAT FAILS TO WORK - SPECIFYING EACH CUSTOMER'S ADFS AS A NEW WSFED AUTH OPTION


        WsFederation.WsFederationAuthenticationOptions Adfs_CompanyA = new WsFederation.WsFederationAuthenticationOptions {
            AuthenticationMode = AuthenticationMode.Passive,
            MetadataAddress = "https://CompanyA.net/FederationMetadata/2007-06/FederationMetadata.xml",
            AuthenticationType = AdfsAuthenticationTypes.CompanyA,
            Wtrealm = "https://www.CompanyA.co.uk/MyAppName"
        };

        WsFederation.WsFederationAuthenticationOptions Adfs_CompanyB = new WsFederation.WsFederationAuthenticationOptions {
            AuthenticationMode = AuthenticationMode.Passive,
            MetadataAddress = "https://CompanyB.net/federationmetadata/2007-06/federationmetadata.xml",
            AuthenticationType = AdfsAuthenticationTypes.CompanyB,
            Wtrealm = "http://www.CompanyB.co.uk/azure/MyAppName"
        };

        // User (who is logged in), route for hyperlink "Link my account with ADFS"
        app.Map("/SSO/LinkUserAccount/ADFS/process", configuration => { configuration.UseWsFederationAuthentication(Adfs_CompanyA); });

        // CompanyA ADFS - single sign-on route
        app.Map("/SSO/Login/CompanyA/ADFS/Go", configuration => { configuration.UseWsFederationAuthentication(Adfs_CompanyA); });

        // CompanyB ADFS - single sign-on route
        app.Map("/SSO/Login/CompanyB/ADFS/Go", configuration => { configuration.UseWsFederationAuthentication(Adfs_CompanyB); });
    }
}

这是我用来发出 OWIN 挑战的代码:

string provider = MyApp.SingleSignOn.GetCustomerAdfsAuthenticationType(customerName);
string redirectUrl = string.Format("{0}/SSO/Login/{1}/ADFS/Go", Request.Url.GetLeftPart(UriPartial.Authority), provider); // creates https://myapp.com/SSO/Login/CompanyA/ADFS/Go for CompanyA users
Context.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = redirectUrl }, provider);
Response.StatusCode = 401;
Response.End();

这是网络表单,但请不要让它阻止 MVC 专业人士的贡献。无论如何,代码实际上是相同的,我正在使用路由。

我遇到的问题是,当用户单击“使用 ADFS 登录”链接时,例如网址变为https://myapp.com/SSO/Login/CompanyA/ADFS 我收到 401 Unauthorized 错误,而不是用户被重定向到 ADFS 登录页面。
在 web.config 中,我允许未经授权访问路径“SSO”。由于某种原因,Challenge() 方法永远不会重定向用户,它只是被忽略并且代码到达它返回 401 的点。字符串provider 的值与 Startup.Auth 中定义的WsFederationAuthenticationOptions.AuthenticationType 值完全匹配。

我已经为此苦苦挣扎了六个星期,所以这是一有机会就获得赏金,一箱啤酒在解决后送到您选择的地址。

【问题讨论】:

    标签: c# asp.net owin adfs katana


    【解决方案1】:

    我解决了这个问题。令人惊讶的是,这就像我在 StartupAuth 结束时错过的一样简单:

    app.UseStageMarker(PipelineStage.Authenticate);
    

    【讨论】:

      【解决方案2】:

      您是否设置了 OWIN 日志记录?有什么线索吗?

      还有Test driving the WS-Federation Authentication Middleware for Katana

      查看IdentityServer 3 中的代码。那里有一个 WS-Fed 插件,文档是 here(在底部)。

      【讨论】:

      • 示例代码似乎设置了一个 ADFS 实例,这是我在许多其他在线项目中遇到的。不过,我看不到 ADFS 与其他提供商一起使用的任何用途。我今天来看看日志记录,虽然这不是我以前做过的事情。
      • IdentityServer 3 支持社交(Google 等)OpenID Connect、OAuth2 和 WS-Fed
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      相关资源
      最近更新 更多