使用 JwtSecurityTokenHandler 反序列化后 ClaimsIdentity AuthenticationType 发生了变化
ClaimsIdentity AuthenticationType changed after deserialization using JwtSecurityTokenHandler
首先,更广泛的背景。
我正在开发一个由单独的 Web API 支持的 Web 应用程序。 Web 应用程序中的身份验证应基于 ActiveDirectory,并且应由 Web API.
处理
因此,Web 应用程序上 AccountController
上的 LogIn
操作仅向 AuthenticationController
发送 post 请求 - 我在那里使用 UserPrincipal 进行 AD 身份验证和主体上下文。
身份验证工作正常,我创建了一些声明。
当我需要 post 将结果返回到网络应用程序时,问题就开始了,这样我就可以像下面那样执行 'SignIn'
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
}
错误是
Expected: ApplicationCookie
Actual: AuthenticationTypes.Federation
其他断言都OK,所以值实际上被保留了。
知道为什么吗?
干杯
我遇到了类似的问题,我通过更改解决了
return claimsPrincipal.Identity as ClaimsIdentity;
至
return new ClaimsIdentity(claimsPrincipal.Claims, "ApplicationCookie");
我通过将 AuthenticationType
参数添加到 TokenValidationParameters
解决了同样的问题。
var validationParameters = new TokenValidationParameters
{
RequireExpirationTime = true,
RequireSignedTokens = true,
ValidateIssuer = true,
ValidIssuer = issuer,
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
ValidateAudience = true,
ValidAudience = audience,
ValidateLifetime = true,
AuthenticationType = "ApplicationCookie"
};
首先,更广泛的背景。
我正在开发一个由单独的 Web API 支持的 Web 应用程序。 Web 应用程序中的身份验证应基于 ActiveDirectory,并且应由 Web API.
处理因此,Web 应用程序上 AccountController
上的 LogIn
操作仅向 AuthenticationController
发送 post 请求 - 我在那里使用 UserPrincipal 进行 AD 身份验证和主体上下文。
身份验证工作正常,我创建了一些声明。
当我需要 post 将结果返回到网络应用程序时,问题就开始了,这样我就可以像下面那样执行 'SignIn'
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
}
错误是
Expected: ApplicationCookie
Actual: AuthenticationTypes.Federation
其他断言都OK,所以值实际上被保留了。
知道为什么吗?
干杯
我遇到了类似的问题,我通过更改解决了
return claimsPrincipal.Identity as ClaimsIdentity;
至
return new ClaimsIdentity(claimsPrincipal.Claims, "ApplicationCookie");
我通过将 AuthenticationType
参数添加到 TokenValidationParameters
解决了同样的问题。
var validationParameters = new TokenValidationParameters
{
RequireExpirationTime = true,
RequireSignedTokens = true,
ValidateIssuer = true,
ValidIssuer = issuer,
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
ValidateAudience = true,
ValidAudience = audience,
ValidateLifetime = true,
AuthenticationType = "ApplicationCookie"
};