Search code examples
.netserializationforms-authenticationdatacontractserializer

Serialize Custom Principal object


I have a custom principal object that I want to be able to serialize so that I can store it in the Userdata of the FormsAuthentication cookie. I'm trying to use the DataContractJsonSerializer to do this, but when the serialization occurs I just get an empty string (no exceptions).

[DataContract]
public class MyPrincipal : IPrincipal
{
    private readonly MyIdentity _identity;

    public MyPrincipal(MyIdentity identity)
    {
        _identity = identity;
    }

    [DataMember]
    public IIdentity Identity
    {
        get { return _identity; }
        set { }
    }

    public bool IsInRole(string role)
    {
        return _identity.AuthGroups.Contains(role, StringComparer.OrdinalIgnoreCase);
    }

    public bool IsInRole(string[] roles)
    {
        return roles.Any(IsInRole);
    }
}

[DataContract]
public class MyIdentity : IIdentity
{
    private readonly MyCustomData _customData;

    public MyIdentity(MyCustomData customData)
    {
        _customData = customData;
    }

    #region IIdentity properties

    [DataMember]
    public string Name
    {
        get { return Username; }
        set {}
    }

    [DataMember]
    public string AuthenticationType
    {
        get { return "Forms"; }
        set {}
    }

    [DataMember]
    public bool IsAuthenticated
    {
        get { return true; }
        set { }
    }

    #endregion

    #region custom properties

    [DataMember]
    public string FirstName
    {
        get { return _customData.FirstName; } 
        set { }
    }
    [DataMember]
    public string LastName
    {
        get { return _customData.LastName; }
        set { }
    }
    [DataMember]
    public string RedwoodID
    {
        get { return _customData.CedarnetRedwoodID; }
        set { }
    }
    [DataMember]
    public string Username
    {
        get { return _customData.NetworkLogin; }
        set { }
    }
    [DataMember]
    public string CuwasTicket
    {
        get { return _customData.CuwasTicket; }
        set { }
    }
    [DataMember]
    public List<string> AuthGroups
    {
        get { return _customData.GroupMembership; }
        set { }
    }

    #endregion
}

And here's the code I'm trying to run to seralize it all:

var serializer = new DataContractJsonSerializer(typeof(MyPrincipal), new List<Type> {typeof(MyPrincipal), typeof(MyIdentity)});
var responseStream = new MemoryStream();
serializer.WriteObject(responseStream, user);
string serializedValue = new StreamReader(responseStream).ReadToEnd();

Solution

  • You miss one line:

    serializer.WriteObject(responseStream, user);
    responseStream.Position = 0; // This!!
    string serializedValue = new StreamReader(responseStream).ReadToEnd();
    

    Remember serializer writes to the stream and StreamReader starts from the current position which is end of the stream.

    On a separate note, serialising IPrincipal and IIdentity does not look like a good thing to do. Reason being they represent a volatile status which can change at any time (e.g. permission revoked after serialisation).