In an ASP.NET Core 3.1 project I am adding some custom claims to the ClaimsIdentity
object after a user logs in.
public void ConfigureServices(IServiceCollection services)
{
...
options.Events.OnTicketReceived = context =>
{
var claimsIdentity = (ClaimsIdentity)context.Principal.Identity;
// custom claims
AddCustomClaims(claimsIdentity);
return;
};
...
}
private void AddCustomClaims(ClaimsIdentity claimsIdentity)
{
claimsIdentity.AddClaim(new Claim("test1", "helloearth!!!"));
claimsIdentity.AddClaim(new Claim("test2", "helloplanet!!!"));
claimsIdentity.AddClaim(new Claim("test3", "helloworld!!!"));
}
If I set a breakpoint on the return;
and take a look at the context.Principal.Identity
object, all three claims appear there.
I don't understand why? I thought I made a copy of context.Principal.Identity
and AddCustomClaims
method only manipulated that copy. But somehow the original object is affected.
CodePudding user response:
This is the age-old confusion between variables and reference types.
To put it simply, you have two major categories of types in .NET, value types and reference types. When you introduce variables into the mix, variables holding value types hold the entire value, like a number, whereas variables holding reference types only hold a reference to an object, and that object is somewhere else in the memory of the computer.
Your .Identity
property there contains such a reference, to an instance of a reference type, and thus when you did
var claimsIdentity = (ClaimsIdentity)context.Principal.Identity;
you didn't actually make another copy of the object, instead, you made a copy of the reference to it. I like to explain this using houses. Your object instance is a house, somewhere, and the variable is like a post-it note with the address to that house.
Your statement didn't build another house, it just made another post-it note with the same address on it.
Or in .NET terms, your variable claimsIdentity
now holds the same reference as was found in .Identity
, but they both refer to the same, single object, somewhere in memory.
So when you changed that object, well, you changed that object.