双OWIN身份验证无法一起使用

时间:2017-12-27 19:17:07

标签: authentication cookies asp.net-mvc-5 owin

对于我的网站,我正在使用OWIN OpenId与第三方身份验证提供程序进行集成,以允许访问者注册/登录/注销。 “秒”

我的应用程序还有一个测试环境,在将这些更改推送到生产环境之前测试所有代码更改。我使用OWIN OpenId以及“First”来保护测试环境免受与另一个第三方认证提供者的公共访问。只有经过身份验证的访问者才能访问测试环境网站。

现在问题是这些都是独立的,但我似乎无法将它们结合起来。我想要实现的是,我可以通过使用First进行身份验证来访问测试环境,然后,作为regluar访问者,使用Second进行身份验证,以查看为注册访问者设计的内容。

这就是我正在做的事情:

两个authnetication提供程序都使用cookie身份验证,但我给了他们一个不同的AuthenticationType来保持它们分开。

if (IsEnabled("First"))
    app.SetDefaultSignInAsAuthenticationType("First");
else
    app.SetDefaultSignInAsAuthenticationType("Second");

// Configure First.
if (IsEnabled("First")) {
    app.UseCookieAuthentication(First.CookieAuthenticationOptions); // AuthenticationType is set to "First" in these options.
    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
    {
        ClientId = First.AADClientId,
        Authority = First.Authority,
        Notifications = new OpenIdConnectAuthenticationNotifications
        {
            AuthenticationFailed = context => { ... },
            RedirectToIdentityProvider = context => { ... }
        },
        AuthenticationType = "First"
    });
    app.Map($"{First.Path}/login", config =>
    {
        config.Run(context =>
        {
            context.Authentication.Challenge(new AuthenticationProperties
                { RedirectUri = First.ReturnUrl, IsPersistent = true  },
                "First"
            );

            context.Response.StatusCode = 401;
            return context.Response.WriteAsync(string.Empty);
        });
    });
}

// Configure Second.
app.UseCookieAuthentication(Second.CookieAuthenticationOptions); // AuthenticationType is set to "Second" in these options.
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    UseTokenLifetime = false,
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        AuthenticationFailed = x => ...,
        RedirectToIdentityProvider = x =>
        {
            var mgr = x.Options.ConfigurationManager as PolicyConfigurationManager;
            if (x.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
            {
                var config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None,
                x.OwinContext.Authentication.AuthenticationResponseRevoke.Properties.Dictionary["PolicyId"]);
                x.ProtocolMessage.IssuerAddress = config.EndSessionEndpoint;
            }
            else
            {
                var config = await mgr.GetConfigurationByPolicyAsync(CancellationToken.None,
                x.OwinContext.Authentication.AuthenticationResponseChallenge.Properties.Dictionary["PolicyId"]);
                x.ProtocolMessage.IssuerAddress = config.AuthorizationEndpoint;
            }

            var redirectUri = Second.ReturnPath;
            x.ProtocolMessage.RedirectUri = redirectUri;
            x.ProtocolMessage.PostLogoutRedirectUri = redirectUri;
        },
        SecurityTokenValidated = x => ...
    },
    Scope = "openid",
    ResponseType = "id_token",
    ReturnUri = Second.ReturnUri,
    ClientId = Second.ClientId,
    ConfigurationManager = GetConfigurationManager()
    AuthenticationType = configuration.AuthenticationType
});
app.Map(Second.LoginPath, config =>
{
    // Trigger unauthorized so that active authentication will redirect to active directory.
    config.Run(context =>
    {
        // Set policy in context to mitigate null ref exception in Startup.Auth OnRedirectToIdentityProvider
        context.Authentication.Challenge(
            new AuthenticationProperties(new Dictionary<string, string>
            {
                {"PolicyId", Second.LoginPolicyId}
            })
            {
                IsPersistent = true,
                RedirectUri = returnUrl
            }, "Second");

        context.Response.StatusCode = 401;

        // Middleware will redirect us instead of using this output.
        return context.Response.WriteAsync(string.Empty);
    });
});
app.Map(Second.ReturnPath, config =>
{
    config.Use((context, next) =>
    {
        // In case of login, we will never get here because we will get redirected by middleware.
        context.Response.Redirect("/");

        return Task.FromResult(0);
    });
});

当启用First时,这允许我执行

var identity = HttpContext.Current.GetOwinContext.Authentication.AuthenticateAsync("Second").Result?.Identity;

对后续请求并具有ClaimsIdentity。但是当启用First时,由于某种原因,上述结果为空。

我注意到当我启用第一个和第二个,并将DefaultSignInAsAuthenticationType设置为“Second”时,它首先不再起作用。如果我同时启用First和Second,并使用以前的身份验证cookie浏览网站,那么一切正常。

我猜测返回方法,某处设置身份验证cookie需要一些AuthenticationType的引用,但我不知道该怎么做。

我错过了什么?

1 个答案:

答案 0 :(得分:2)

诀窍是在配置Second时将AuthenticationType添加到TokenValidationParameters,如下所示:

String storeToDataSink (contains all the book names)
testRunner.testCase.testSteps["DataSink"].setPropertyValue("Book1", 
storeToDataSink.toString())