OWIN OpenID连接中间件不能用ClaimsPrincipal替换当前用户

时间:2015-06-30 19:06:37

标签: c# asp.net-mvc owin identityserver3 openid-connect

我有一个现有的MVC5应用程序,我正在使用AspNetIdentity转换为使用ThinkTecture Identity Server 3 v2。 OpenID提供商并不是我遇到的最大问题,因为它看起来效果很好。安全令牌已经过验证,我正在处理方法中的SecurityTokenValidated通知,以获取其他用户信息声明并向声明集添加系统特定的权限声明,类似于以下代码:

OWIN中间件

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = "https://localhost:44300/identity",
    Caption = "My Application",
    ClientId = "implicitclient",
    ClientSecret = Convert.ToBase64String(SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes("secret"))),
    RedirectUri = "http://localhost:8080/",
    ResponseType = "id_token token",
    Scope = "openid profile email roles",
    SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
    UseTokenLifetime = false,
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        SecurityTokenValidated = ClaimsTransformer.GenerateUserIdentityAsync
    }
});

Claim Transformer

public static async Task GenerateUserIdentityAsync(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
    var identityUser = new ClaimsIdentity(
        notification.AuthenticationTicket.Identity.Claims,
        notification.AuthenticationTicket.Identity.AuthenticationType,
        ClaimTypes.Name,
        ClaimTypes.Role);

    var userInfoClient = new UserInfoClient(new Uri(notification.Options.Authority + "/connect/userinfo"),
        notification.ProtocolMessage.AccessToken);

    var userInfo = await userInfoClient.GetAsync();
    identityUser.AddClaims(userInfo.Claims.Select(t => new Claim(t.Item1, t.Item2)));

    var userName = identityUser.FindFirst("preferred_username").Value;
    var user = MembershipProxy.GetUser(userName);
    var userId = user.PersonID;
    identityUser.AddClaim(new Claim(ClaimTypes.Name, userId.ToString(), ClaimValueTypes.Integer));

    // Populate additional claims

    notification.AuthenticationTicket = new AuthenticationTicket(identityUser, notification.AuthenticationTicket.Properties);
}

问题是在变换器末尾分配给身份验证票证的ClaimsIdentity永远不会填充在System.Web管道中。当OnAuthenticationChallenge期间请求到达我的控制器时,我检查User属性以找到一个匿名的WindowsPrincipal,其中类似的WindowsIdentity实例分配给Identity属性,就好像web配置的system.web/authentication/@mode属性设置为None(至少我相信这是该模式的行为。)

中间件可能导致用户设置主体,或者在使用匿名Windows身份进行System.Web处理期间替换它的原因是什么?我无法追踪这一点。

编辑:无论是否处理了SecurityTokenValidated通知并增加了声明,都会发生这种情况。

编辑2:原因似乎是在我的web.config中使用带有cookie的ASP.NET状态服务会话状态服务器。配置条目是:

<sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" timeout="30" cookieless="UseCookies" />

这看起来与Microsoft.Owin.Host.SystemWeb #197中报告的问题有关,其中cookie不会从OWIN请求上下文持久存储到System.Web管道中。建议提供各种各样的解决方法,但我希望有人能够权威地指出我对这个问题进行适当审查的解决方案。

2 个答案:

答案 0 :(得分:0)

如果你要捕获一个小提琴手的踪迹,你会看到任何.AspNet.Cookies。 我怀疑饼干没有被写入。您可以使用分布式缓存并取消cookie。

答案 1 :(得分:0)

我认为你需要包含cookie认证中间件,因为.AspNet.Cookies是由中间件编写的。这是您可以集成该中间件的方法

app.UseCookieAuthentication(new CookieAuthenticationOptions());
  

注意:请确保它应该位于openid connect中间件之上

有关CookieAuthenticationOptions的更多详细信息,请转到此链接https://msdn.microsoft.com/en-us/library/microsoft.owin.security.cookies.cookieauthenticationoptions(v=vs.113).aspx