File: System\IdentityModel\Tokens\SecurityTokenHandler.cs
Project: ndp\cdf\src\WCF\IdentityModel\System.IdentityModel.csproj (System.IdentityModel)
//-----------------------------------------------------------------------
// <copyright file="SecurityTokenHandler.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
 
namespace System.IdentityModel.Tokens
{
    using System.Collections.ObjectModel;
    using System.IdentityModel.Configuration;
    using System.IdentityModel.Diagnostics.Application;
    using System.IdentityModel.Selectors;
    using System.Runtime.Diagnostics;
    using System.Security.Claims;
    using System.Xml;
 
    /// <summary>
    /// Defines the interface for a Security Token Handler.
    /// </summary>
    public abstract class SecurityTokenHandler : ICustomIdentityConfiguration
    {
        private SecurityTokenHandlerCollection collection;
        private SecurityTokenHandlerConfiguration configuration;
        private EventTraceActivity eventTraceActivity;
 
        /// <summary>
        /// Creates an instance of <see cref="SecurityTokenHandler"/>
        /// </summary>
        protected SecurityTokenHandler()
        {
        }
 
        private EventTraceActivity EventTraceActivity
        {
            get
            {
                if (this.eventTraceActivity == null)
                {
                    this.eventTraceActivity = EventTraceActivity.GetFromThreadOrCreate();
                }
 
                return this.eventTraceActivity;
            }
        }
 
        /// <summary>
        /// Gets a value indicating whether this handler supports validation of tokens 
        /// handled by this instance.
        /// </summary>v
        /// <returns>'True' if the instance is capable of SecurityToken
        /// validation.</returns>
        public virtual bool CanValidateToken
        {
            get { return false; }
        }
 
        /// <summary>
        /// Gets a value indicating whether the class provides serialization functionality to serialize token handled 
        /// by this instance.
        /// </summary>
        /// <returns>true if the WriteToken method can serialize this token.</returns>
        public virtual bool CanWriteToken
        {
            get { return false; }
        }
 
        /// <summary>
        /// Gets or sets the <see cref="SecurityTokenHandlerConfiguration" />
        /// </summary>
        public SecurityTokenHandlerConfiguration Configuration
        {
            get { return this.configuration; }
            set { this.configuration = value; }
        }
 
        /// <summary>
        /// Gets or sets the SecurityTokenHandlerCollection that this SecurityTokenHandler
        /// is part of. This property should never be set directly. When the SecurityTokenHandler
        /// is added to a collection this property is automatically set.
        /// </summary>
        public SecurityTokenHandlerCollection ContainingCollection
        {
            get 
            { 
                return this.collection;
            }
 
            internal set 
            { 
                this.collection = value;
            }
        }
 
        /// <summary>
        /// Gets the System.Type of the SecurityToken this instance handles.
        /// </summary>
        public abstract Type TokenType
        {
            get;
        }
 
        /// <summary>
        /// Indicates whether the current XML element can be read as a token 
        /// of the type handled by this instance.
        /// </summary>
        /// <param name="reader">An XML reader positioned at a start 
        /// element. The reader should not be advanced.</param>
        /// <returns>'True' if the ReadToken method can the element.</returns>
        public virtual bool CanReadToken(XmlReader reader)
        {
            return false;
        }
 
        /// <summary>
        /// Indicates whether the current token string can be read as a token 
        /// of the type handled by this instance.
        /// </summary>
        /// <param name="tokenString">The token string thats needs to be read.</param>
        /// <returns>'True' if the ReadToken method can parse the token string.</returns>
        public virtual bool CanReadToken(string tokenString)
        {
            return false;
        }
        
        /// <summary>
        /// Deserializes from XML a token of the type handled by this instance.
        /// </summary>
        /// <param name="reader">An XML reader positioned at the token's start 
        /// element.</param>
        /// <returns>SecurityToken instance.</returns>
        public virtual SecurityToken ReadToken(XmlReader reader)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.ID4008, "SecurityTokenHandler", "ReadToken")));
        }
 
        /// <summary>
        /// Deserializes from XML a token of the type handled by this instance.
        /// </summary>
        /// <param name="reader">An XML reader positioned at the token's start 
        /// element.</param>
        /// <param name="tokenResolver">The SecrityTokenResolver that contains out-of-band and cached tokens.</param>
        /// <returns>SecurityToken instance.</returns>
        public virtual SecurityToken ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver)
        {
            // The default implementation ignores the SecurityTokenResolver and delegates the call to the 
            // ReadToken method that takes a XmlReader.
            return this.ReadToken(reader);
        }
 
        /// <summary>
        /// Deserializes from string a token of the type handled by this instance.
        /// </summary>
        /// <param name="tokenString">The string to be deserialized.</param>
        /// <returns>SecurityToken instance which represents the serialized token.</returns>
        public virtual SecurityToken ReadToken(string tokenString)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.ID4008, "SecurityTokenHandler", "ReadToken")));
        }
 
        /// <summary>
        /// Serializes to XML a token of the type handled by this instance.
        /// </summary>
        /// <param name="writer">The XML writer.</param>
        /// <param name="token">A token of type TokenType.</param>
        public virtual void WriteToken(XmlWriter writer, SecurityToken token)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.ID4008, "SecurityTokenHandler", "WriteToken")));
        }
 
        /// <summary>
        /// Serializes to string a token of the type handled by this instance.
        /// </summary>
        /// <param name="token">A token of type TokenType.</param>
        /// <returns>The serialized token.</returns>
        public virtual string WriteToken(SecurityToken token)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.ID4008, "SecurityTokenHandler", "WriteToken")));
        }
 
        /// <summary>
        /// Indicates if the current XML element is pointing to a KeyIdentifierClause that
        /// can be serialized by this instance.
        /// </summary>
        /// <param name="reader">An XML reader positioned at the start element. 
        /// The reader should not be advanced.</param>
        /// <returns>true if the ReadKeyIdentifierClause can read the element.</returns>
        public virtual bool CanReadKeyIdentifierClause(XmlReader reader)
        {
            return false;
        }
 
        /// <summary>
        /// Deserializes the XML to a KeyIdentifierClause that references a token 
        /// handled by this instance.
        /// </summary>
        /// <param name="reader">An XML reader positioned at the KeyIdentifierClause start element.</param>
        /// <returns>SecurityKeyIdentifierClause instance.</returns>
        public virtual SecurityKeyIdentifierClause ReadKeyIdentifierClause(XmlReader reader)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.ID4008, "SecurityTokenHandler", "ReadKeyIdentifierClause")));
        }
 
        /// <summary>
        /// Indicates if the given SecurityKeyIdentifierClause can be serialized by this
        /// instance.
        /// </summary>
        /// <param name="securityKeyIdentifierClause">SecurityKeyIdentifierClause to be serialized.</param>
        /// <returns>true if the given SecurityKeyIdentifierClause can be serialized.</returns>
        public virtual bool CanWriteKeyIdentifierClause(SecurityKeyIdentifierClause securityKeyIdentifierClause)
        {
            return false;
        }
 
        /// <summary>
        /// Serializes to XML a SecurityKeyIdentifierClause that this instance supports.
        /// </summary>
        /// <param name="writer">The XML writer.</param>
        /// <param name="securityKeyIdentifierClause">The SecurityKeyIdentifierClause to be used to serialize the token.</param>
        public virtual void WriteKeyIdentifierClause(XmlWriter writer, SecurityKeyIdentifierClause securityKeyIdentifierClause)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.ID4008, "SecurityTokenHandler", "WriteKeyIdentifierClause")));
        }
 
        /// <summary>
        /// Called by the STS to create a token given a token descriptor. 
        /// </summary>
        /// <param name="tokenDescriptor">Describes the token; properties such 
        /// as ValidFrom, AppliesTo, EncryptingCredentials, Claims, etc., are filled in 
        /// before the call to create token. </param>
        /// <returns>A SecurityToken that matches the properties of the token descriptor.</returns>
        public virtual SecurityToken CreateToken(SecurityTokenDescriptor tokenDescriptor)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.ID4008, "SecurityTokenHandler", "CreateToken")));
        }
 
        /// <summary>
        /// Creates the security token reference for tokens handled by this instance.
        /// </summary>
        /// <param name="token">The SecurityToken instance for which the references needs to be
        /// created.</param>
        /// <param name="attached">Boolean that indicates if a attached or unattached
        /// reference needs to be created.</param>
        /// <returns>A SecurityKeyIdentifierClause that identifies the given token.</returns>
        public virtual SecurityKeyIdentifierClause CreateSecurityTokenReference(SecurityToken token, bool attached)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.ID4008, "SecurityTokenHandler", "CreateSecurityTokenReference")));
        }
 
        /// <summary>
        /// The URI used in requests to identify a token of the type handled
        /// by this instance. 
        /// </summary>
        /// <remarks>
        /// For example, this should be the URI value used 
        /// in the RequestSecurityToken's TokenType element to request this
        /// sort of token.
        /// </remarks>
        /// <returns>The set of URIs that identify the token this handler supports.</returns>
        public abstract string[] GetTokenTypeIdentifiers();
 
        /// <summary>
        /// Validates a <see cref="SecurityToken"/>.
        /// </summary>
        /// <param name="token">The <see cref="SecurityToken"/> to validate.</param>
        /// <returns>The <see cref="ReadOnlyCollection{T}"/> of <see cref="ClaimsIdentity"/> representing the identities contained in the token.</returns>
        /// <remarks>Derived types will validate specific tokens.</remarks>
        public virtual ReadOnlyCollection<ClaimsIdentity> ValidateToken(SecurityToken token)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.ID4008, "SecurityTokenHandler", "ValidateToken")));
        }
 
        /// <summary>
        /// Throws if a token is detected as being replayed.
        /// Override this method in your derived class to detect replays.
        /// </summary>
        /// <param name="token">The token to check for replay.</param>
        protected virtual void DetectReplayedToken(SecurityToken token)
        {
        }
 
        /// <summary>
        /// Load custom configuration from Xml
        /// </summary>
        /// <param name="nodelist">Custom configuration elements</param>
        public virtual void LoadCustomConfiguration(XmlNodeList nodelist)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.ID0023, this.GetType().AssemblyQualifiedName)));
        }
 
        protected void TraceTokenValidationSuccess(SecurityToken token)
        {
            if (TD.TokenValidationSuccessIsEnabled())
            {
                TD.TokenValidationSuccess(this.EventTraceActivity, token.GetType().ToString(), token.Id);
            }
        }
 
        protected void TraceTokenValidationFailure(SecurityToken token, string errorMessage)
        {
            if (TD.TokenValidationFailureIsEnabled())
            {
                TD.TokenValidationFailure(this.EventTraceActivity, token.GetType().ToString(), token.Id, errorMessage);
            }
        }
    }
}