|
//------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
using System.Runtime.Serialization;
using System.Xml;
using System.IO;
namespace System.IdentityModel.Tokens
{
/// <summary>
/// Represents a serializable version of a token that can be attached to a <see cref="System.Security.Claims.ClaimsIdentity"/> to retain the
/// original token that was used to create <see cref="System.Security.Claims.ClaimsIdentity"/>
/// </summary>
[Serializable]
public class BootstrapContext : ISerializable
{
SecurityToken _token;
string _tokenString;
byte[] _tokenBytes;
SecurityTokenHandler _tokenHandler;
const string _tokenTypeKey = "K";
const string _tokenKey = "T";
const char _securityTokenType = 'T';
const char _stringTokenType = 'S';
const char _byteTokenType = 'B';
protected BootstrapContext(SerializationInfo info, StreamingContext context)
{
if (info == null)
return;
switch (info.GetChar(_tokenTypeKey))
{
case _securityTokenType:
{
SecurityTokenHandler sth = context.Context as SecurityTokenHandler;
if (sth != null)
{
using (XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(Convert.FromBase64String(info.GetString(_tokenKey)), XmlDictionaryReaderQuotas.Max))
{
reader.MoveToContent();
if (sth.CanReadToken(reader))
{
string tokenName = reader.LocalName;
string tokenNamespace = reader.NamespaceURI;
SecurityToken token = sth.ReadToken(reader);
if (token == null)
{
_tokenString = Text.Encoding.UTF8.GetString(Convert.FromBase64String(info.GetString(_tokenKey)));
}
else
{
_token = token;
}
}
}
}
else
{
_tokenString = Text.Encoding.UTF8.GetString(Convert.FromBase64String(info.GetString(_tokenKey)));
}
}
break;
case _stringTokenType:
{
_tokenString = info.GetString(_tokenKey);
}
break;
case _byteTokenType:
{
_tokenBytes = (byte[])info.GetValue(_tokenKey, typeof(byte[]));
}
break;
default:
break;
}
}
/// <summary>
/// A SecurityToken and a SecurityTokenHandler that can serialize the token.
/// </summary>
/// <param name="token"><see cref="SecurityToken"/> that can be serialized. Cannot be null.</param>
/// <param name="tokenHandler"><see cref="SecurityTokenHandler"/> that is responsible for serializing the token. Cannon be null.</param>
/// <exception cref="ArgumentNullException"> thrown if 'token' or 'tokenHandler' is null.</exception>
/// <remarks>The <see cref="SecurityTokenHandler"/> is used not used to deserialize the token as it cannot be assumed to exist</remarks>
public BootstrapContext(SecurityToken token, SecurityTokenHandler tokenHandler)
{
if (token == null)
{
throw new ArgumentNullException("token");
}
if (tokenHandler == null)
{
throw new ArgumentNullException("tokenHandler");
}
_token = token;
_tokenHandler = tokenHandler;
}
/// <summary>
/// String that represents a SecurityToken.
/// </summary>
/// <param name="token">string that represents a token. Can not be null.</param>
/// <exception cref="ArgumentNullException"> thrown if 'token' is null.</exception>
public BootstrapContext(string token)
{
if (token == null)
{
throw new ArgumentNullException("token");
}
_tokenString = token;
}
/// <summary>
/// String that represents a SecurityToken.
/// </summary>
/// <param name="token">string that represents a token. Can not be null.</param>
/// <exception cref="ArgumentNullException"> thrown if 'token' is null.</exception>
public BootstrapContext(byte[] token)
{
if (token == null)
{
throw new ArgumentNullException("token");
}
_tokenBytes = token;
}
#region ISerializable Members
/// <summary>
/// Called to serialize this context.
/// </summary>
/// <param name="info"><see cref="SerializationInfo"/> container for storing data. Cannot be null.</param>
/// <param name="context"><see cref="StreamingContext"/> contains the context for streaming and optionally additional user data.</param>
/// <exception cref="ArgumentNullException"> thrown if 'info' is null.</exception>
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (_tokenBytes != null)
{
info.AddValue(_tokenTypeKey, _byteTokenType);
info.AddValue(_tokenKey, _tokenBytes);
}
else if (_tokenString != null)
{
info.AddValue(_tokenTypeKey, _stringTokenType);
info.AddValue(_tokenKey, _tokenString);
}
else if (_token != null && _tokenHandler != null)
{
using (MemoryStream ms = new MemoryStream())
{
info.AddValue(_tokenTypeKey, _securityTokenType);
using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(ms, Text.Encoding.UTF8, false))
{
_tokenHandler.WriteToken(writer, _token);
writer.Flush();
info.AddValue(_tokenKey, Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length));
}
}
}
}
#endregion
/// <summary>
/// Gets the string that was passed in constructor. If a different constructor was used, will be null.
/// </summary>
public byte[] TokenBytes
{
get { return _tokenBytes; }
}
/// <summary>
/// Gets the string that was passed in constructor. If a different constructor was used, will be null.
/// </summary>
public string Token
{
get { return _tokenString; }
}
/// <summary>
/// Gets the SecurityToken that was passed in constructor. If a different constructor was used, will be null.
/// </summary>
public SecurityToken SecurityToken
{
get { return _token; }
}
/// <summary>
/// Gets the SecurityTokenHandler that was passed in constructor. If a different constructor was used, will be null.
/// </summary>
public SecurityTokenHandler SecurityTokenHandler
{
get { return _tokenHandler; }
}
}
}
|