OpenId Connect中间件未在WebForms应用程序

时间:2015-09-26 08:38:56

标签: authentication cookies owin middleware openid-connect

我试图将OpenId Connect集成到长期现有的webforms应用程序中。我能够迁移应用程序以使用OWIN,并且我使用OpenIdConnectAuthenticationMiddleware对我的IdP提供程序进行身份验证。一切顺利,直到我需要构建从IdP获得的新身份并设置cookie - 我认为哪个部分没有发生。

我的Startup.Configure方法的重要部分:

app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/login.aspx"),
    CookieManager = new SystemWebCookieManager() //custom cookie manager
});


app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = "https://[development_domain]/core",
    ClientId = "VDWeb",
    ResponseType = "code id_token token",
    Scope = "openid profile",
    UseTokenLifetime = true,
    SignInAsAuthenticationType = "Cookies",
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        SecurityTokenValidated = async n =>
        {
            var userInfo = await EndpointAndTokenHelper.CallUserInfoEndpoint(n.ProtocolMessage.AccessToken);

            //now store Preferred name :
            var prefNameClaim = new Claim(
                Thinktecture.IdentityModel.Client.JwtClaimTypes.PreferredUserName,
                userInfo.Value<string>("preferred_username"));

            var myIdentity = new ClaimsIdentity(
                n.AuthenticationTicket.Identity.AuthenticationType,
                Thinktecture.IdentityModel.Client.JwtClaimTypes.PreferredUserName,
                Thinktecture.IdentityModel.Client.JwtClaimTypes.Role);

            myIdentity.AddClaim(prefNameClaim);

            //add unique_user_key claim
            var subjectClaim = n.AuthenticationTicket.Identity.FindFirst(Thinktecture.IdentityModel.Client.JwtClaimTypes.Subject);

            myIdentity.AddClaim(new Claim("unique_user_key", subjectClaim.Value));
            myIdentity.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));

            var ticket = new AuthenticationTicket(myIdentity, n.AuthenticationTicket.Properties);
            var currentUtc = new SystemClock().UtcNow;
            ticket.Properties.IssuedUtc = currentUtc;
            ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromHours(12));
            n.AuthenticationTicket = ticket;                
        },
    }
});

我可以确认AuthentocationTicket已正确填充但未设置auth cookie。我确实知道这个问题https://katanaproject.codeplex.com/workitem/197,我已经尝试过针对这个问题提供的所有解决方法但没有帮助。有趣的是,当我尝试将自己的cookie放入SecurityTokenValidated事件 - n.Response.Cookies.Append("Test", "Test");时,我可以看到cookie已正确设置。

其中一个解决方法建议实现自己的CookieManager。令我好奇的是,当我在这个自定义管理器中将断点放入cookie setter时,它没有被击中,即中间件似乎甚至没有尝试设置cookie。所以我有一个主要问题 - 中间件究竟会在什么时候尝试设置cookie?是在我设置AuthenticationTicket时吗?

编辑1:添加更多信息。我试图与另一个网络应用程序进行比较,这次MVC,我配置使用相同的IdP,并按预期工作。两个应用程序的启动代码都是相同的。通过SecurityTokenValidated事件进行调试时,我可以看到MVC应用程序(正在工作)创建了System.Security.Principal.WindowsPrincipal身份,而webforms app(非工作)创建了System.Security.Principal.GenericIdentity身份。

我还添加了这个小小的剪切

app.UseStageMarker(PipelineStage.Authenticate);
app.Use((context, next) =>
{
    var identity = context.Request.User.Identity;
    return next.Invoke();
});

只是为了查看在此管道阶段填充的身份。对于MVC应用程序(工作),我通过设置AuthenticationTicket看到我添加的身份,对于webforms应用程序,我仍然看到未经过身份验证的GenericIdentity。

2 个答案:

答案 0 :(得分:4)

好的,这很令人尴尬 - 问题出现在CookieAuthenticationOptions中,显然AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie NOT AuthenticationType = "Cookies"相同。一旦设置了以后的方式,它就可以正常工作。

答案 1 :(得分:0)

您是否可以使用默认的Cookie管理器,看看是否会导致设置Cookie?