File: System\ServiceModel\Security\WrappedX509SecurityTokenAuthenticator.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
 
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Policy;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Claims;
 
namespace System.ServiceModel.Security
{
    /// <summary>
    /// Wraps a X509SecurityTokenHandler. Delegates the token authentication call the inner tokenAuthenticator. 
    /// Wraps the returned ClaimsIdentities into an AuthorizationPolicy that supports IAuthorizationPolicy
    /// </summary>
    internal class WrappedX509SecurityTokenAuthenticator : X509SecurityTokenAuthenticator
    {
        X509SecurityTokenHandler _wrappedX509SecurityTokenHandler;
        ExceptionMapper _exceptionMapper;
 
        /// <summary>
        /// Initializes an instance of <see cref="WrappedX509SecurityTokenAuthenticator"/>
        /// </summary>
        /// <param name="wrappedX509SecurityTokenHandler">X509SecurityTokenHandler to wrap.</param>
        /// <param name="exceptionMapper">Converts token validation exceptions to SOAP faults.</param>
        public WrappedX509SecurityTokenAuthenticator( 
            X509SecurityTokenHandler wrappedX509SecurityTokenHandler, 
            ExceptionMapper exceptionMapper )
            : base( X509CertificateValidator.None, GetMapToWindowsSetting( wrappedX509SecurityTokenHandler ), true )
        {
            if ( wrappedX509SecurityTokenHandler == null )
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "wrappedX509SecurityTokenHandler" );
            }
 
            if ( exceptionMapper == null )
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "exceptionMapper" );
            }
 
            _wrappedX509SecurityTokenHandler = wrappedX509SecurityTokenHandler;
            _exceptionMapper = exceptionMapper;
        }
 
        /// <summary>
        /// Validates the token using the wrapped token handler and generates IAuthorizationPolicy
        /// wrapping the returned ClaimsIdentities.
        /// </summary>
        /// <param name="token">Token to be validated.</param>
        /// <returns>Read-only collection of IAuthorizationPolicy</returns>
        protected override ReadOnlyCollection<IAuthorizationPolicy> ValidateTokenCore( SecurityToken token )
        {
            ReadOnlyCollection<ClaimsIdentity> identities = null;
            try
            {
                identities = _wrappedX509SecurityTokenHandler.ValidateToken(token);
            }
            catch ( Exception ex )
            {
                if ( !_exceptionMapper.HandleSecurityTokenProcessingException( ex ) )
                {
                    throw;
                }
            }
 
            // tlsnego will dispose of the x509, when we write out the bootstrap we will get a dispose error.
 
            bool shouldSaveBootstrapContext = SecurityTokenHandlerConfiguration.DefaultSaveBootstrapContext;
            if ( _wrappedX509SecurityTokenHandler.Configuration != null )
            {
                shouldSaveBootstrapContext = _wrappedX509SecurityTokenHandler.Configuration.SaveBootstrapContext;
            }
 
            if ( shouldSaveBootstrapContext )
            {
                X509SecurityToken x509Token = token as X509SecurityToken;
                SecurityToken tokenToCache;
                if ( x509Token != null )
                {
                    tokenToCache = new X509SecurityToken( x509Token.Certificate );
                }
                else
                {
                    tokenToCache = token;
                }
 
                BootstrapContext bootstrapContext = new BootstrapContext(tokenToCache, _wrappedX509SecurityTokenHandler);
                foreach (ClaimsIdentity identity in identities)
                {
                    identity.BootstrapContext = bootstrapContext;
                }
            }
 
            List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>(1);
            policies.Add(new AuthorizationPolicy(identities));
 
            return policies.AsReadOnly();
        }
 
        static bool GetMapToWindowsSetting( X509SecurityTokenHandler securityTokenHandler )
        {
            if ( securityTokenHandler == null )
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "securityTokenHandler" );
            }
 
            return securityTokenHandler.MapToWindows;
        }
    }
}