【问题标题】:Double OWIN authentication not working together双重 OWIN 身份验证无法协同工作
【发布时间】:2023-03-09 22:27:01
【问题描述】:

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

我的应用程序也有一个测试环境,在将这些更改推送到生产环境之前,所有代码更改都会在该环境中进行测试。我使用 OWIN OpenId 以及“First”,通过另一个 3rd 方身份验证提供程序保护测试环境免受公共访问。只有经过身份验证的访问者才能访问测试环境网站。

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

这就是我正在做的事情:

两个身份验证提供程序都使用 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 被启用时,由于某种原因,上面的 Result 为空。

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

我猜想在某处设置身份验证 cookie 的返回方法需要一些 AuthenticationType 的引用,但我不知道在哪里做。

我错过了什么?

【问题讨论】:

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


    【解决方案1】:

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

    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,
        // ADD THIS TO MAKE IT WORK:
        TokenValidationParameters = new TokenValidationParameters
            {
                AuthenticationType = configuration.AuthenticationType
            }
    });
    

    【讨论】:

      猜你喜欢
      • 2014-09-19
      • 2015-09-23
      • 2023-04-05
      • 1970-01-01
      • 2014-10-22
      • 2015-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多