I implemented my own ITicketStore implementation in .NET Core which handles storing session cookies in a redis database. My keys are a simple guid:
public async Task<string> StoreAsync(AuthenticationTicket ticket)
{
var log = new StringWriter();
var guid = Guid.NewGuid();
var key = "MyCustomCache"+ guid.ToString();
await RenewAsync(key, ticket);
return key;
}
public Task RenewAsync(string key, AuthenticationTicket ticket)
{
var options = new DistributedCacheEntryOptions();
var expiresUtc = ticket.Properties.ExpiresUtc;
if (expiresUtc.HasValue)
{
options.SetAbsoluteExpiration(expiresUtc.Value);
}
byte[] val = SerializeToBytes(ticket);
_cache.Set(key, val, options);
return Task.FromResult(0);
}
However in the browser when I check the value of the cookie it seems to be encoded/encrypted somehow (rather than the guid I generated):
When the cookie is passed to my application I notice that its been transformed back to the original value I created in StoreAsync:
public Task<AuthenticationTicket> RetrieveAsync(string key)
{
// Key passed in here will not be the value in the image above. Instead it will be what was
// generated in StoreAsync
AuthenticationTicket ticket;
byte[] bytes = null;
bytes = _cache.Get(key);
ticket = DeserializeFromBytes(bytes);
return Task.FromResult(ticket);
}
What exactly is .NET Core doing to my keys to encrypt/encode the key? Will this affect my ability to load balance my application? I know that in the default session storage mechanism .NET Core encrypts the session cookies using a dynamic key per machine.
The authentication cookie is being encrypted with the default data protection.
Here is where the key is added to the cookie (source):
if (Options.SessionStore != null)
{
if (_sessionKey != null)
{
await Options.SessionStore.RemoveAsync(_sessionKey);
}
_sessionKey = await Options.SessionStore.StoreAsync(ticket);
var principal = new ClaimsPrincipal(
new ClaimsIdentity(
new[] { new Claim(SessionIdClaim, _sessionKey, ClaimValueTypes.String, Options.ClaimsIssuer) },
Options.ClaimsIssuer));
ticket = new AuthenticationTicket(principal, null, Scheme.Name);
}
var cookieValue = Options.TicketDataFormat.Protect(ticket, GetTlsTokenBinding());
When switching to a SessionStore, the session key is just added as a claim and then the cookie is protected.