简体   繁体   English

使用多个ADFS + Cookies时未执行OWIN Challenge()方法

[英]OWIN Challenge() method not executed when using multiple ADFS + Cookies

My ASP.Net app uses OWIN/Katana/Claims, and allows login using: 我的ASP.Net应用程序使用OWIN / Katana / Claims,并允许使用以下方式登录:

  1. Traditional username/password (exists for all users) 传统的用户名/密码(适用于所有用户)
  2. Google 谷歌
  3. Azure AD Azure AD

It works perfectly, and all the necessary redirects/claims transfers work well (the user NameIdentifier/Provider(/tenant) details are passed back to my app so the unique id values can be linked up). 它运行完美,并且所有必要的重定向/声明传输均正常运行(用户NameIdentifier / Provider(/ tenant)详细信息已传递回我的应用程序,因此可以链接唯一的ID值)。 Note that users do not sign up/register for the app - access is provisioned by their organisation's super-user, and a username/password sent to them which they can then hook up with Google/Azure. 请注意,用户不会注册/注册该应用-访问权限是由其组织的超级用户提供的,用户名/密码会发送给他们,然后他们可以与Google / Azure联系。

However, I now need to extend this functionality to allow users to hook up to their organisation's ADFS provider. 但是,我现在需要扩展此功能,以允许用户连接到其组织的ADFS提供程序。 The only working example for this that's remotely close is here ( tutorial / code ), but it is strictly based on ADFS-only. 唯一可以远程完成的示例在此处( 教程 / 代码 ),但是它严格基于仅ADFS。 When I adapt this into my project, it doesn't work. 当我将其调整到我的项目中时,它不起作用。

My entire StartupAuth file is shown below. 我的整个StartupAuth文件如下所示。 I appreciate that there may be configuration errors, but based on the scraps of samples I've found over the last six weeks, this is the best I've had. 我很欣赏可能存在配置错误,但是根据我在过去六周中发现的一些报废,这是我所拥有的最好的。

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); });
    }
}

Here is the code I use to issue an OWIN Challenge: 这是我用来发出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();

This is webforms, but please don't let that stop MVC pro's from contributing. 这是网络表单,但是请不要阻止MVC专业人士的贡献。 The code is virtually identical anyway and I'm using routes. 无论如何,代码实际上是相同的,我正在使用路由。

The problem I have is that when the user clicks on the "sign-on with ADFS" link, eg URL becomes https://myapp.com/SSO/Login/CompanyA/ADFS I get an 401 Unauthorized error, instead of the user being redirected to the ADFS login page. 我遇到的问题是,当用户单击“使用ADFS登录”链接时,例如URL变为https://myapp.com/SSO/Login/CompanyA/ADFS,则会收到401未经授权的错误,而不是用户被重定向到ADFS登录页面。
In web.config, I allow unauthorized access to path "SSO". 在web.config中,我允许未经授权的访问路径“ SSO”。 For some reason the Challenge() method never redirects the user, it simply gets ignored and the code reaches the point where it returns a 401. The value of string provider exactly matches the WsFederationAuthenticationOptions.AuthenticationType value defined in Startup.Auth. 由于某种原因, Challenge()方法从不重定向用户,它只会被忽略,并且代码到达返回401的地步。字符串provider的值与Startup.Auth中定义的WsFederationAuthenticationOptions.AuthenticationType值完全匹配。

I've been sturggling with this now for six weeks, so this is getting a bounty at the first opportunity, and a crate of beer delivered to your chosen address when it is solved. 我已经为此烦恼了六个星期,所以这是第一个机会,这将是一笔赏金,解决之后,还将一箱啤酒运送到您选择的地址。

I solved the problem. 我解决了问题。 Amazingly, it was as simple as me missing this from the end of StartupAuth: 令人惊讶的是,就像我在StartupAuth末尾错过了这个一样简单:

app.UseStageMarker(PipelineStage.Authenticate);

Have you set up OWIN logging? 您是否设置了OWIN日志记录? Any clues there? 有什么线索吗?

Also Test driving the WS-Federation Authentication Middleware for Katana . 还可以测试驱动Katana的WS-Federation身份验证中间件

Have a look at the code in IdentityServer 3 . 看一下IdentityServer 3中的代码。 There's a WS-Fed plugin there and the documentation is here (at the bottom). 那里有一个WS-Fed插件,文档在这里 (底部)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM