I'm using the Owin OpenIdConnectAuthentication module in my app, and am trying to move my session state to Redis. I'm using Microsoft.Web.Redis.RedisSessionStateProvider
for this. When I update my web.config to add the RedisSessionStateProvider
I start getting this error:
Type 'Microsoft.Owin.Security.AuthenticationTicket' in Assembly 'Microsoft.Owin.Security, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' is not marked as serializable.
Stack Trace
[SerializationException: Type 'Microsoft.Owin.Security.AuthenticationTicket' in Assembly 'Microsoft.Owin.Security, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' is not marked as serializable.]
System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type) +10951483
System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context) +230
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() +121
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder) +182
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder) +51
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck) +540
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck) +131
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph) +12
Microsoft.Web.Redis.RedisUtility.GetBytesFromObject(Object data) in c:\TeamCity\buildAgent\work\f55792526e6d9089\src\Shared\RedisUtility.cs:65
Microsoft.Web.Redis.RedisUtility.AppendUpdatedOrNewItemsInList(ChangeTrackingSessionStateItemCollection sessionItems, List`1 list) in c:\TeamCity\buildAgent\work\f55792526e6d9089\src\Shared\RedisUtility.cs:37
Microsoft.Web.Redis.RedisConnectionWrapper.TryUpdateIfLockIdMatchPrepare(Object lockId, ISessionStateItemCollection data, Int32 sessionTimeout, String[]& keyArgs, Object[]& valueArgs) in c:\TeamCity\buildAgent\work\f55792526e6d9089\src\RedisSessionStateProvider\RedisConnectionWrapper.cs:323
Microsoft.Web.Redis.RedisConnectionWrapper.TryUpdateAndReleaseLockIfLockIdMatch(Object lockId, ISessionStateItemCollection data, Int32 sessionTimeout) in c:\TeamCity\buildAgent\work\f55792526e6d9089\src\RedisSessionStateProvider\RedisConnectionWrapper.cs:350
Microsoft.Web.Redis.RedisSessionStateProvider.SetAndReleaseItemExclusive(HttpContext context, String id, SessionStateStoreData item, Object lockId, Boolean newItem) in c:\TeamCity\buildAgent\work\f55792526e6d9089\src\RedisSessionStateProvider\RedisSessionStateProvider.cs:408
System.Web.SessionState.SessionStateModule.OnReleaseState(Object source, EventArgs eventArgs) +565
System.Web.SessionState.SessionStateModule.OnEndRequest(Object source, EventArgs eventArgs) +139
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69
Am I missing some config somewhere? All the documentation I can find about serializing AuthenticationTicket
objects is for OAuth server implementations.
We were using the AspNetAuthSessionStore sample from Katana. Apparently this sample only works for InProc session state. We made the following changes to resolve this issue by manually serializing the AuthenticationTicket
:
public Task<string> StoreAsync(AuthenticationTicket ticket)
{
string key = Guid.NewGuid().ToString();
HttpContext httpContext = HttpContext.Current;
CheckSessionAvailable(httpContext);
//httpContext.Session[key + ".Ticket"] = ticket; // Remove
var ticketSerializer = new TicketSerializer(); // Add
var ticketBytes = ticketSerializer.Serialize(ticket); // Add
httpContext.Session[key + ".Ticket"] = ticketBytes; // Add
return Task.FromResult(key);
}