220 lines
7.4 KiB
C#
220 lines
7.4 KiB
C#
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Security.Claims;
|
|
using Microsoft.Owin.Security.DataHandler.Serializer;
|
|
|
|
namespace Microsoft.Owin.Security.Interop
|
|
{
|
|
// This MUST be kept in sync with Microsoft.AspNetCore.Authentication.DataHandler.TicketSerializer
|
|
public class AspNetTicketSerializer : IDataSerializer<AuthenticationTicket>
|
|
{
|
|
private const string DefaultStringPlaceholder = "\0";
|
|
private const int FormatVersion = 5;
|
|
|
|
public static AspNetTicketSerializer Default { get; } = new AspNetTicketSerializer();
|
|
|
|
public virtual byte[] Serialize(AuthenticationTicket ticket)
|
|
{
|
|
using (var memory = new MemoryStream())
|
|
{
|
|
using (var writer = new BinaryWriter(memory))
|
|
{
|
|
Write(writer, ticket);
|
|
}
|
|
return memory.ToArray();
|
|
}
|
|
}
|
|
|
|
public virtual AuthenticationTicket Deserialize(byte[] data)
|
|
{
|
|
using (var memory = new MemoryStream(data))
|
|
{
|
|
using (var reader = new BinaryReader(memory))
|
|
{
|
|
return Read(reader);
|
|
}
|
|
}
|
|
}
|
|
|
|
public virtual void Write(BinaryWriter writer, AuthenticationTicket ticket)
|
|
{
|
|
writer.Write(FormatVersion);
|
|
writer.Write(ticket.Identity.AuthenticationType);
|
|
|
|
var identity = ticket.Identity;
|
|
if (identity == null)
|
|
{
|
|
throw new ArgumentNullException("ticket.Identity");
|
|
}
|
|
|
|
// There is always a single identity
|
|
writer.Write(1);
|
|
WriteIdentity(writer, identity);
|
|
PropertiesSerializer.Write(writer, ticket.Properties);
|
|
}
|
|
|
|
protected virtual void WriteIdentity(BinaryWriter writer, ClaimsIdentity identity)
|
|
{
|
|
var authenticationType = identity.AuthenticationType ?? string.Empty;
|
|
|
|
writer.Write(authenticationType);
|
|
WriteWithDefault(writer, identity.NameClaimType, ClaimsIdentity.DefaultNameClaimType);
|
|
WriteWithDefault(writer, identity.RoleClaimType, ClaimsIdentity.DefaultRoleClaimType);
|
|
|
|
// Write the number of claims contained in the identity.
|
|
writer.Write(identity.Claims.Count());
|
|
|
|
foreach (var claim in identity.Claims)
|
|
{
|
|
WriteClaim(writer, claim);
|
|
}
|
|
|
|
var bootstrap = identity.BootstrapContext as string;
|
|
if (!string.IsNullOrEmpty(bootstrap))
|
|
{
|
|
writer.Write(true);
|
|
writer.Write(bootstrap);
|
|
}
|
|
else
|
|
{
|
|
writer.Write(false);
|
|
}
|
|
|
|
if (identity.Actor != null)
|
|
{
|
|
writer.Write(true);
|
|
WriteIdentity(writer, identity.Actor);
|
|
}
|
|
else
|
|
{
|
|
writer.Write(false);
|
|
}
|
|
}
|
|
|
|
protected virtual void WriteClaim(BinaryWriter writer, Claim claim)
|
|
{
|
|
WriteWithDefault(writer, claim.Type, claim.Subject?.NameClaimType ?? ClaimsIdentity.DefaultNameClaimType);
|
|
writer.Write(claim.Value);
|
|
WriteWithDefault(writer, claim.ValueType, ClaimValueTypes.String);
|
|
WriteWithDefault(writer, claim.Issuer, ClaimsIdentity.DefaultIssuer);
|
|
WriteWithDefault(writer, claim.OriginalIssuer, claim.Issuer);
|
|
|
|
// Write the number of properties contained in the claim.
|
|
writer.Write(claim.Properties.Count);
|
|
|
|
foreach (var property in claim.Properties)
|
|
{
|
|
writer.Write(property.Key ?? string.Empty);
|
|
writer.Write(property.Value ?? string.Empty);
|
|
}
|
|
}
|
|
|
|
public virtual AuthenticationTicket Read(BinaryReader reader)
|
|
{
|
|
if (reader.ReadInt32() != FormatVersion)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var scheme = reader.ReadString();
|
|
|
|
// Any identities after the first will be ignored.
|
|
var count = reader.ReadInt32();
|
|
if (count < 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var identity = ReadIdentity(reader);
|
|
var properties = PropertiesSerializer.Read(reader);
|
|
|
|
return new AuthenticationTicket(identity, properties);
|
|
}
|
|
|
|
protected virtual ClaimsIdentity ReadIdentity(BinaryReader reader)
|
|
{
|
|
var authenticationType = reader.ReadString();
|
|
var nameClaimType = ReadWithDefault(reader, ClaimsIdentity.DefaultNameClaimType);
|
|
var roleClaimType = ReadWithDefault(reader, ClaimsIdentity.DefaultRoleClaimType);
|
|
|
|
// Read the number of claims contained
|
|
// in the serialized identity.
|
|
var count = reader.ReadInt32();
|
|
|
|
var identity = new ClaimsIdentity(authenticationType, nameClaimType, roleClaimType);
|
|
|
|
for (int index = 0; index != count; ++index)
|
|
{
|
|
var claim = ReadClaim(reader, identity);
|
|
|
|
identity.AddClaim(claim);
|
|
}
|
|
|
|
// Determine whether the identity
|
|
// has a bootstrap context attached.
|
|
if (reader.ReadBoolean())
|
|
{
|
|
identity.BootstrapContext = reader.ReadString();
|
|
}
|
|
|
|
// Determine whether the identity
|
|
// has an actor identity attached.
|
|
if (reader.ReadBoolean())
|
|
{
|
|
identity.Actor = ReadIdentity(reader);
|
|
}
|
|
|
|
return identity;
|
|
}
|
|
|
|
protected virtual Claim ReadClaim(BinaryReader reader, ClaimsIdentity identity)
|
|
{
|
|
var type = ReadWithDefault(reader, identity.NameClaimType);
|
|
var value = reader.ReadString();
|
|
var valueType = ReadWithDefault(reader, ClaimValueTypes.String);
|
|
var issuer = ReadWithDefault(reader, ClaimsIdentity.DefaultIssuer);
|
|
var originalIssuer = ReadWithDefault(reader, issuer);
|
|
|
|
var claim = new Claim(type, value, valueType, issuer, originalIssuer, identity);
|
|
|
|
// Read the number of properties stored in the claim.
|
|
var count = reader.ReadInt32();
|
|
|
|
for (var index = 0; index != count; ++index)
|
|
{
|
|
var key = reader.ReadString();
|
|
var propertyValue = reader.ReadString();
|
|
|
|
claim.Properties.Add(key, propertyValue);
|
|
}
|
|
|
|
return claim;
|
|
}
|
|
|
|
private static void WriteWithDefault(BinaryWriter writer, string value, string defaultValue)
|
|
{
|
|
if (string.Equals(value, defaultValue, StringComparison.Ordinal))
|
|
{
|
|
writer.Write(DefaultStringPlaceholder);
|
|
}
|
|
else
|
|
{
|
|
writer.Write(value);
|
|
}
|
|
}
|
|
|
|
private static string ReadWithDefault(BinaryReader reader, string defaultValue)
|
|
{
|
|
var value = reader.ReadString();
|
|
if (string.Equals(value, DefaultStringPlaceholder, StringComparison.Ordinal))
|
|
{
|
|
return defaultValue;
|
|
}
|
|
return value;
|
|
}
|
|
}
|
|
} |