C# 使用JwtSecurityTokenHandler反序列化后更改了ClaimSideEntity AuthenticationType

C# 使用JwtSecurityTokenHandler反序列化后更改了ClaimSideEntity AuthenticationType,c#,authentication,asp.net-web-api,claims-based-identity,C#,Authentication,Asp.net Web Api,Claims Based Identity,首先,更广泛的背景 我正在开发一个由单独的web API支持的web应用程序。web应用程序中的身份验证应基于ActiveDirectory,并应由web API处理 因此,web应用程序上的AccountController上的LogIn操作只向AuthenticationController发送post请求,在那里我使用UserPrincipal和PrincipalContext进行AD身份验证。 身份验证工作正常,我创建了一些声明 当我需要将结果发布回web应用程序时,问题就开始了,这样我

首先,更广泛的背景

我正在开发一个由单独的web API支持的web应用程序。web应用程序中的身份验证应基于ActiveDirectory,并应由web API处理

因此,web应用程序上的
AccountController
上的
LogIn
操作只向
AuthenticationController
发送post请求,在那里我使用UserPrincipal和PrincipalContext进行AD身份验证。 身份验证工作正常,我创建了一些声明

当我需要将结果发布回web应用程序时,问题就开始了,这样我就可以像下面那样进行“登录”

if (result.Claims == null)
            {
                this.Logger.Error($"Something went wrong when discovering identity of user [{model.UserName}]");
                throw new InvalidOperationException(Strings_Error.ErrorWhileDiscoveringUserIdentity);
            }
            IAuthenticationManager authenticationManager = this.HttpContext.GetOwinContext().Authentication;
            authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
            authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = false }, result.Claims);
我正在使用JwtSecurityTokenHandler序列化声明,以便将它们附加到来自Web Api控制器的响应消息。 序列化过程如下所示:

 public static string GenerateToken(this ClaimsIdentity identity)
    {
        SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Encoding.Default.GetBytes(ClaimsIndentitySerializer.SecurityKey));
        SigningCredentials signingCredentials = new SigningCredentials(securityKey,SecurityAlgorithms.HmacSha256Signature);
        JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();

        SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = identity,
            SigningCredentials = signingCredentials,
            Issuer = IssuerKey,
            Audience = "http://www.mycompany.com",
        };

        SecurityToken token = tokenHandler.CreateToken(tokenDescriptor);
        string tokenString = tokenHandler.WriteToken(token);

        return tokenString;
    }
然后,从字符串生成索赔:

public static ClaimsIdentity ReadToken(this string token)
    {
        JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
        SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Encoding.Default.GetBytes(ClaimsIndentitySerializer.SecurityKey));

        TokenValidationParameters validationParameters = new TokenValidationParameters()
        {
            ValidAudience = "http://www.mycompany.com",
            ValidIssuer = IssuerKey,
            IssuerSigningKey = securityKey
        };

        SecurityToken validatedToken = new JwtSecurityToken() as SecurityToken;
        ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(token, validationParameters, out validatedToken);

        return claimsPrincipal.Identity as ClaimsIdentity;
    }
我已经创建了一个单元测试来检查索赔在处理后是否匹配。。。而且,令我惊讶的是,它们有着显著的不同

public void TestClaimsSerialization()
    {
        ClaimsIdentity identity = new ClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie, ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType);
        identity.AddClaim(new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "Active Directory"));
        identity.AddClaim(new Claim(ClaimTypes.Name, "TestName"));
        identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, "TestNameIdentifier"));
        var token = identity.GenerateToken();
        var deserialized = token.ReadToken();
        Assert.Equal(identity.Name, deserialized.Name);
        Assert.Equal(identity.Claims.FirstOrDefault(x=>x.Type == ClaimTypes.NameIdentifier).Value, deserialized.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value);
        Assert.Equal(identity.AuthenticationType, deserialized.AuthenticationType); //the last assert fails
    }
错误是
应为:applicationcokie
实际:AuthenticationTypes.Federation

其他断言是可以的,因此这些值实际上是保留的

知道为什么吗


干杯

我有一个类似的问题,我通过改变来解决它

return claimsPrincipal.Identity as ClaimsIdentity;


我通过将
AuthenticationType
参数添加到
TokenValidationParameters
解决了相同的问题

var validationParameters=新的令牌验证参数
{
RequireExpirationTime=true,
RequiredSignedTokens=真,
validateisuer=true,
ValidisUser=发行人,
ValidateSuersigningKey=true,
IssuerSigningKey=签名密钥,
ValidateAudience=true,
勇敢=观众,
ValidateLifetime=true,
AuthenticationType=“ApplicationOkie”
};

“当我需要将结果发回web应用程序时,问题就开始了。”。您的代码是否有任何问题,或者只是在
testclaimserialization
中显示了一个不符合预期的值?@RuardvanElburg-好吧,这里的测试方法与代码运行时的测试方法相同-我从
的token.ReadToken()
中获得的声明具有不同的身份验证类型(联合身份验证与应用程序身份验证),所以它不会对我的用户进行身份验证。
return new ClaimsIdentity(claimsPrincipal.Claims, "​​ApplicationCookie");