< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Security.FederatedSecurityTokenManager
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Security/FederatedSecurityTokenManager.cs
Line coverage
30%
Covered lines: 59
Uncovered lines: 132
Coverable lines: 191
Total lines: 584
Line coverage: 30.8%
Branch coverage
21%
Covered branches: 29
Total branches: 138
Branch coverage: 21%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Security/FederatedSecurityTokenManager.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.Collections.ObjectModel;
 7using System.Globalization;
 8using CoreWCF.Description;
 9using CoreWCF.IdentityModel;
 10using CoreWCF.IdentityModel.Protocols.WSTrust;
 11using CoreWCF.IdentityModel.Selectors;
 12using CoreWCF.IdentityModel.Tokens;
 13using CoreWCF.Security.Tokens;
 14
 15namespace CoreWCF.Security
 16{
 17    /// <summary>
 18    /// SecurityTokenManager that enables plugging custom tokens easily.
 19    /// The SecurityTokenManager provides methods to register custom token providers,
 20    /// serializers and authenticators. It can wrap another Token Managers and
 21    /// delegate token operation calls to it if required.
 22    /// </summary>
 23    /// <remarks>
 24    /// Framework use only - this is an implementation adapter class that is used to expose
 25    /// the Framework SecurityTokenHandlers to WCF.
 26    /// </remarks>
 27    internal sealed class FederatedSecurityTokenManager : ServiceCredentialsSecurityTokenManager
 28    {
 029        private static readonly string s_listenUriProperty = "http://schemas.microsoft.com/ws/2006/05/servicemodel/secur
 30        private ExceptionMapper _exceptionMapper;
 31        private SecurityTokenResolver _defaultTokenResolver;
 232        private readonly object _syncObject = new object();
 33        private readonly ReadOnlyCollection<CookieTransform> _cookieTransforms;
 34        private readonly SessionSecurityTokenCache _tokenCache;
 35
 36        /// <summary>
 37        /// Initializes an instance of <see cref="FederatedSecurityTokenManager"/>.
 38        /// </summary>
 39        /// <param name="parentCredentials">ServiceCredentials that created this instance of TokenManager.</param>
 40        /// <exception cref="ArgumentNullException">The argument 'parentCredentials' is null.</exception>
 41        public FederatedSecurityTokenManager(ServiceCredentials parentCredentials, ReadOnlyCollection<CookieTransform> c
 242            : base(parentCredentials)
 43        {
 244            if (parentCredentials == null)
 45            {
 046                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(parentCredentials));
 47            }
 48
 249            if (parentCredentials.IdentityConfiguration == null)
 50            {
 051                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(parentCredentials.IdentityConfig
 52            }
 53
 254            _exceptionMapper = parentCredentials.ExceptionMapper;
 255            SecurityTokenHandlers = parentCredentials.IdentityConfiguration.SecurityTokenHandlers;
 256            _tokenCache = SecurityTokenHandlers.Configuration.Caches.SessionSecurityTokenCache;
 257            _cookieTransforms = cookieTransforms;
 258        }
 59
 60        /// <summary>
 61        /// Returns the list of SecurityTokenHandlers.
 62        /// </summary>
 863        public SecurityTokenHandlerCollection SecurityTokenHandlers { get; }
 64
 65        /// <summary>
 66        /// Gets or sets the ExceptionMapper to be used when throwing exceptions.
 67        /// </summary>
 68        public ExceptionMapper ExceptionMapper
 69        {
 70            get
 71            {
 072                return _exceptionMapper;
 73            }
 74            set
 75            {
 076                _exceptionMapper = value ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(valu
 077            }
 78        }
 79
 80        #region SecurityTokenManager Implementation
 81
 82        /// <summary>
 83        /// Overriden from the base class. Creates the requested Token Authenticator.
 84        /// Looks up the list of Token Handlers registered with the token Manager
 85        /// based on the TokenType Uri in the SecurityTokenRequirement. If none is found,
 86        /// then the call is delegated to the inner Token Manager.
 87        /// </summary>
 88        /// <param name="tokenRequirement">Security Token Requirement for which the Authenticator should be created.</pa
 89        /// <param name="outOfBandTokenResolver">Token resolver that resolves any out-of-band tokens.</param>
 90        /// <returns>Instance of Security Token Authenticator.</returns>
 91        /// <exception cref="ArgumentNullException">'tokenRequirement' parameter is null.</exception>
 92        /// <exception cref="NotSupportedException">No Authenticator is registered for the given token type.</exception>
 93        public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequir
 94        {
 295            if (tokenRequirement == null)
 96            {
 097                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(tokenRequirement));
 98            }
 99
 2100            outOfBandTokenResolver = null;
 2101            string tokenType = tokenRequirement.TokenType;
 102            //
 103            // When the TokenRequirement.TokenType is null, we treat this as a SAML issued token case. It may be SAML 1.
 104            //
 2105            if (string.IsNullOrEmpty(tokenType))
 106            {
 2107                return CreateSamlSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver);
 108            }
 109
 110            //
 111            // When the TokenType is set, build a token authenticator for the specified token type.
 112            //
 0113            SecurityTokenHandler securityTokenHandler = SecurityTokenHandlers[tokenType];
 114
 115            // Check for a registered authenticator
 116            SecurityTokenAuthenticator securityTokenAuthenticator;
 0117            if ((securityTokenHandler != null) && (securityTokenHandler.CanValidateToken))
 118            {
 0119                outOfBandTokenResolver = GetDefaultOutOfBandTokenResolver();
 120
 0121                if (StringComparer.Ordinal.Equals(tokenType, SecurityTokenTypes.UserName))
 122                {
 0123                    if (!(securityTokenHandler is UserNameSecurityTokenHandler upSecurityTokenHandler))
 124                    {
 0125                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0126                            new InvalidOperationException(SR.Format(SR.ID4072, securityTokenHandler.GetType(), tokenType
 127                    }
 0128                    securityTokenAuthenticator = new WrappedUserNameSecurityTokenAuthenticator(upSecurityTokenHandler, _
 129                }
 0130                else if (StringComparer.Ordinal.Equals(tokenType, SecurityTokenTypes.Kerberos))
 131                {
 0132                    securityTokenAuthenticator = CreateInnerSecurityTokenAuthenticator(tokenRequirement, out outOfBandTo
 133                }
 134                //TODO: not sure if this is supported
 0135                else if (StringComparer.Ordinal.Equals(tokenType, SecurityTokenTypes.Rsa))
 136                {
 0137                    throw new PlatformNotSupportedException();
 138                    //RsaSecurityTokenHandler rsaSecurityTokenHandler = securityTokenHandler as RsaSecurityTokenHandler;
 139                    //if (rsaSecurityTokenHandler == null)
 140                    //{
 141                    //    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 142                    //        new InvalidOperationException(SR.Format(SR.ID4072, securityTokenHandler.GetType(), tokenTy
 143                    //}
 144                    //securityTokenAuthenticator = new WrappedRsaSecurityTokenAuthenticator(rsaSecurityTokenHandler, _ex
 145                }
 0146                else if (StringComparer.Ordinal.Equals(tokenType, SecurityTokenTypes.X509Certificate))
 147                {
 0148                    if (!(securityTokenHandler is X509SecurityTokenHandler x509SecurityTokenHandler))
 149                    {
 0150                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0151                            new InvalidOperationException(SR.Format(SR.ID4072, securityTokenHandler.GetType(), tokenType
 152                    }
 0153                    securityTokenAuthenticator = new WrappedX509SecurityTokenAuthenticator(x509SecurityTokenHandler, _ex
 154                }
 0155                else if (StringComparer.Ordinal.Equals(tokenType, SecurityTokenTypes.SamlTokenProfile11) ||
 0156                          StringComparer.Ordinal.Equals(tokenType, SecurityTokenTypes.OasisWssSamlTokenProfile11))
 157                {
 0158                    if (!(securityTokenHandler is SamlSecurityTokenHandler saml11SecurityTokenHandler))
 159                    {
 0160                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0161                            new InvalidOperationException(SR.Format(SR.ID4072, securityTokenHandler.GetType(), tokenType
 162                    }
 163
 0164                    if (saml11SecurityTokenHandler.Configuration == null)
 165                    {
 0166                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation(SR.Format(SR.ID4274));
 167                    }
 168
 0169                    securityTokenAuthenticator = new WrappedSaml11SecurityTokenAuthenticator(saml11SecurityTokenHandler,
 170                    // The out-of-band token resolver will be used by WCF to decrypt any encrypted SAML tokens.
 0171                    outOfBandTokenResolver = saml11SecurityTokenHandler.Configuration.ServiceTokenResolver;
 172                }
 0173                else if (StringComparer.Ordinal.Equals(tokenType, SecurityTokenTypes.Saml2TokenProfile11) ||
 0174                          StringComparer.Ordinal.Equals(tokenType, SecurityTokenTypes.OasisWssSaml2TokenProfile11))
 175                {
 0176                    if (!(securityTokenHandler is Saml2SecurityTokenHandler saml2SecurityTokenHandler))
 177                    {
 0178                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0179                            new InvalidOperationException(SR.Format(SR.ID4072, securityTokenHandler.GetType(), tokenType
 180                    }
 181
 0182                    if (saml2SecurityTokenHandler.Configuration == null)
 183                    {
 0184                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation(SR.Format(SR.ID4274));
 185                    }
 186
 0187                    securityTokenAuthenticator = new WrappedSaml2SecurityTokenAuthenticator(saml2SecurityTokenHandler, _
 188                    // The out-of-band token resolver will be used by WCF to decrypt any encrypted SAML tokens.
 0189                    outOfBandTokenResolver = saml2SecurityTokenHandler.Configuration.ServiceTokenResolver;
 190                }
 0191                else if (StringComparer.Ordinal.Equals(tokenType, ServiceModelSecurityTokenTypes.SecureConversation))
 192                {
 0193                    if (!(tokenRequirement is RecipientServiceModelSecurityTokenRequirement tr))
 194                    {
 0195                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation(SR.Format(SR.ID4240, tokenR
 196                    }
 197
 0198                    securityTokenAuthenticator = SetupSecureConversationWrapper(tr, securityTokenHandler as SessionSecur
 199                }
 200                else
 201                {
 0202                    securityTokenAuthenticator = new SecurityTokenAuthenticatorAdapter(securityTokenHandler, _exceptionM
 203                }
 204            }
 205            else
 206            {
 0207                if (tokenType == ServiceModelSecurityTokenTypes.SecureConversation
 0208                    || tokenType == ServiceModelSecurityTokenTypes.MutualSslnego
 0209                    || tokenType == ServiceModelSecurityTokenTypes.AnonymousSslnego
 0210                    || tokenType == ServiceModelSecurityTokenTypes.SecurityContext
 0211                    || tokenType == ServiceModelSecurityTokenTypes.Spnego)
 212                {
 0213                    if (!(tokenRequirement is RecipientServiceModelSecurityTokenRequirement tr))
 214                    {
 0215                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation(SR.Format(SR.ID4240, tokenR
 216                    }
 217
 0218                    securityTokenAuthenticator = SetupSecureConversationWrapper(tr, null, out outOfBandTokenResolver);
 219                }
 220                else
 221                {
 0222                    securityTokenAuthenticator = CreateInnerSecurityTokenAuthenticator(tokenRequirement, out outOfBandTo
 223                }
 224            }
 225
 0226            return securityTokenAuthenticator;
 227        }
 228
 229        /// <summary>
 230        /// Helper method to setup the WrappedSecureConversttion
 231        /// </summary>
 232        private SecurityTokenAuthenticator SetupSecureConversationWrapper(RecipientServiceModelSecurityTokenRequirement 
 233        {
 234            // This code requires Orcas SP1 to compile.
 235            // WCF expects this securityTokenAuthenticator to support:
 236            // 1. IIssuanceSecurityTokenAuthenticator
 237            // 2. ICommunicationObject is needed for this to work right.
 238            // WCF opens a listener in this STA that handles the nego and uses an internal class for negotiating the
 239            // the bootstrap tokens.  We want to handle ValidateToken to return our authorization policies and surface t
 240
 241            // when sp1 is installed, use this one.
 242            //SecurityTokenAuthenticator sta = base.CreateSecureConversationTokenAuthenticator(tokenRequirement as Recip
 243
 244            // use this code if SP1 is not installed
 0245            SecurityTokenAuthenticator sta = base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenR
 0246            SessionSecurityTokenHandler sessionTokenHandler = tokenHandler;
 247
 248            //
 249            // If there is no SCT handler here, create one.
 250            //
 0251            if (tokenHandler == null)
 252            {
 0253                sessionTokenHandler = new SessionSecurityTokenHandler(_cookieTransforms, SessionSecurityTokenHandler.Def
 0254                {
 0255                    ContainingCollection = SecurityTokenHandlers,
 0256                    Configuration = SecurityTokenHandlers.Configuration
 0257                };
 258            }
 259
 0260            if (ServiceCredentials != null)
 261            {
 0262                sessionTokenHandler.Configuration.MaxClockSkew = ServiceCredentials.IdentityConfiguration.MaxClockSkew;
 263            }
 264
 0265            SctClaimsHandler claimsHandler = new SctClaimsHandler(
 0266                                                    SecurityTokenHandlers,
 0267                                                    GetNormalizedEndpointId(tokenRequirement));
 268
 0269            WrappedSessionSecurityTokenAuthenticator wssta = new WrappedSessionSecurityTokenAuthenticator(sessionTokenHa
 0270                                                                                                           claimsHandler
 0271            WrappedTokenCache wrappedTokenCache = new WrappedTokenCache(_tokenCache, claimsHandler);
 0272            SetWrappedTokenCache(wrappedTokenCache, sta, wssta, claimsHandler);
 0273            outOfBandTokenResolver = wrappedTokenCache;
 274
 0275            return wssta;
 276        }
 277
 278        /// <summary>
 279        /// The purpose of this method is to set our WrappedTokenCache as the token cache for SCT's.
 280        /// And to set our OnIssuedToken callback when in cookie mode.
 281        /// We have to use reflection here as this is a private method.
 282        /// </summary>
 283        private static void SetWrappedTokenCache(
 284            WrappedTokenCache wrappedTokenCache,
 285            SecurityTokenAuthenticator sta,
 286            WrappedSessionSecurityTokenAuthenticator wssta,
 287            SctClaimsHandler claimsHandler)
 288        {
 0289            if (sta is SecuritySessionSecurityTokenAuthenticator)
 290            {
 0291                (sta as SecuritySessionSecurityTokenAuthenticator).IssuedTokenCache = wrappedTokenCache;
 292            }
 293            //else if (sta is AcceleratedTokenAuthenticator)
 294            //{
 295            //    (sta as AcceleratedTokenAuthenticator).IssuedTokenCache = wrappedTokenCache;
 296            //}
 0297            else if (sta is SpnegoTokenAuthenticator)
 298            {
 0299                (sta as SpnegoTokenAuthenticator).IssuedTokenCache = wrappedTokenCache;
 300            }
 301            //else if (sta is TlsnegoTokenAuthenticator)
 302            //{
 303            //    (sta as TlsnegoTokenAuthenticator).IssuedTokenCache = wrappedTokenCache;
 304            //}
 305
 306            // we need to special case this as the OnTokenIssued callback is not hooked up in the cookie mode case.
 0307            if (sta is IIssuanceSecurityTokenAuthenticator issuanceTokenAuthenticator)
 308            {
 0309                issuanceTokenAuthenticator.IssuedSecurityTokenHandler = claimsHandler.OnTokenIssued;
 0310                issuanceTokenAuthenticator.RenewedSecurityTokenHandler = claimsHandler.OnTokenRenewed;
 311            }
 0312        }
 313
 314        /// <summary>
 315        /// Overriden from the base class. Creates the requested Token Serializer.
 316        /// Returns a Security Token Serializer that is wraps the list of token
 317        /// hanlders registerd and also the serializers from the inner token manager.
 318        /// </summary>
 319        /// <param name="version">SecurityTokenVersion of the serializer to be created.</param>
 320        /// <returns>Instance of SecurityTokenSerializer.</returns>
 321        /// <exception cref="ArgumentNullException">Input parameter is null.</exception>
 322        public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
 323        {
 2324            if (version == null)
 325            {
 0326                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(version));
 327            }
 328
 2329            TrustVersion trustVersion = null;
 2330            SecureConversationVersion scVersion = null;
 331
 14332            foreach (string securitySpecification in version.GetSecuritySpecifications())
 333            {
 6334                if (StringComparer.Ordinal.Equals(securitySpecification, WSTrustFeb2005Constants.NamespaceURI))
 335                {
 0336                    trustVersion = TrustVersion.WSTrustFeb2005;
 337                }
 6338                else if (StringComparer.Ordinal.Equals(securitySpecification, WSTrust13Constants.NamespaceURI))
 339                {
 2340                    trustVersion = TrustVersion.WSTrust13;
 341                }
 4342                else if (StringComparer.Ordinal.Equals(securitySpecification, WSSecureConversationFeb2005Constants.Names
 343                {
 0344                    scVersion = SecureConversationVersion.WSSecureConversationFeb2005;
 345                }
 4346                else if (StringComparer.Ordinal.Equals(securitySpecification, WSSecureConversation13Constants.Namespace)
 347                {
 2348                    scVersion = SecureConversationVersion.WSSecureConversation13;
 349                }
 350
 6351                if (trustVersion != null && scVersion != null)
 352                {
 2353                    break;
 354                }
 355            }
 356
 2357            if (trustVersion == null)
 358            {
 0359                trustVersion = TrustVersion.WSTrust13;
 360            }
 361
 2362            if (scVersion == null)
 363            {
 0364                scVersion = SecureConversationVersion.WSSecureConversation13;
 365            }
 366
 2367            WsSecurityTokenSerializerAdapter adapter = new WsSecurityTokenSerializerAdapter(SecurityTokenHandlers,
 2368                GetSecurityVersion(version), trustVersion, scVersion, false, ServiceCredentials.IssuedTokenAuthenticatio
 2369                ServiceCredentials.SecureConversationAuthentication.SecurityStateEncoder,
 2370                ServiceCredentials.SecureConversationAuthentication.SecurityContextClaimTypes)
 2371            {
 2372                MapExceptionsToSoapFaults = true,
 2373                ExceptionMapper = _exceptionMapper
 2374            };
 375
 2376            return adapter;
 377        }
 378
 379        /// <summary>
 380        /// The out-of-band token resolver to be used if the authenticator does
 381        /// not provide another.
 382        /// </summary>
 383        /// <remarks>By default this will create the resolver with the service certificate and
 384        /// know certificates collections specified in the service credentials when the STS is
 385        /// hosted inside WCF.</remarks>
 386        private SecurityTokenResolver GetDefaultOutOfBandTokenResolver()
 387        {
 0388            if (_defaultTokenResolver == null)
 389            {
 0390                lock (_syncObject)
 391                {
 0392                    if (_defaultTokenResolver == null)
 393                    {
 394                        //
 395                        // Create default Out-Of-Band SecurityResolver.
 396                        //
 0397                        List<SecurityToken> outOfBandTokens = new List<SecurityToken>();
 0398                        if (base.ServiceCredentials.ServiceCertificate.Certificate != null)
 399                        {
 0400                            outOfBandTokens.Add(new X509SecurityToken(base.ServiceCredentials.ServiceCertificate.Certifi
 401                        }
 402
 0403                        if ((base.ServiceCredentials.IssuedTokenAuthentication.KnownCertificates != null) && (base.Servi
 404                        {
 0405                            for (int i = 0; i < base.ServiceCredentials.IssuedTokenAuthentication.KnownCertificates.Coun
 406                            {
 0407                                outOfBandTokens.Add(new X509SecurityToken(base.ServiceCredentials.IssuedTokenAuthenticat
 408                            }
 409                        }
 410
 0411                        _defaultTokenResolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(outOfBandTokens
 412                    }
 0413                }
 414            }
 415
 0416            return _defaultTokenResolver;
 417        }
 418        /// <summary>
 419        /// There is a bug in WCF where the version obtained from the public SecurityTokenVersion strings is wrong.
 420        /// The internal MessageSecurityTokenVersion has the right version.
 421        /// </summary>
 422        internal static SecurityVersion GetSecurityVersion(SecurityTokenVersion tokenVersion)
 423        {
 2424            if (tokenVersion == null)
 425            {
 0426                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(tokenVersion));
 427            }
 428
 429            //
 430            // Workaround for WCF bug.
 431            // In .NET 3.5 WCF returns the wrong Token Specification. We need to reflect on the
 432            // internal code so we can access the SecurityVersion directly instead of depending
 433            // on the security specification.
 434            //
 2435            if (tokenVersion is MessageSecurityTokenVersion)
 436            {
 2437                SecurityVersion sv = (tokenVersion as MessageSecurityTokenVersion).SecurityVersion;
 438
 2439                if (sv != null)
 440                {
 2441                    return sv;
 442                }
 443            }
 444            else
 445            {
 0446                if (tokenVersion.GetSecuritySpecifications().Contains(WSSecurity11Constants.Namespace))
 447                {
 0448                    return SecurityVersion.WSSecurity11;
 449                }
 0450                else if (tokenVersion.GetSecuritySpecifications().Contains(WSSecurity10Constants.Namespace))
 451                {
 0452                    return SecurityVersion.WSSecurity10;
 453                }
 454            }
 455
 0456            return SecurityVersion.WSSecurity11;
 457        }
 458
 459        #endregion // SecurityTokenManager Implementation
 460
 461        /// <summary>
 462        /// This method creates the inner security token authenticator from the base class.
 463        /// The wrapped token cache is initialized with this authenticator.
 464        /// </summary>
 465        private SecurityTokenAuthenticator CreateInnerSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequireme
 466        {
 0467            SecurityTokenAuthenticator securityTokenAuthenticator = base.CreateSecurityTokenAuthenticator(tokenRequireme
 0468            SctClaimsHandler claimsHandler = new SctClaimsHandler(
 0469                                        SecurityTokenHandlers,
 0470                                        GetNormalizedEndpointId(tokenRequirement));
 471
 0472            SetWrappedTokenCache(new WrappedTokenCache(_tokenCache, claimsHandler), securityTokenAuthenticator, null, cl
 0473            return securityTokenAuthenticator;
 474        }
 475
 476        /// <summary>
 477        /// This method creates a SAML security token authenticator when token type is null.
 478        /// It wraps the SAML 1.1 and the SAML 2.0 token handlers that are configured.
 479        /// If no token handler was found, then the inner token manager is created.
 480        /// </summary>
 481        private SecurityTokenAuthenticator CreateSamlSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequiremen
 482        {
 2483            outOfBandTokenResolver = null;
 2484            SamlSecurityTokenHandler saml11SecurityTokenHandler = SecurityTokenHandlers[SecurityTokenTypes.SamlTokenProf
 2485            Saml2SecurityTokenHandler saml2SecurityTokenHandler = SecurityTokenHandlers[SecurityTokenTypes.Saml2TokenPro
 486
 2487            if (saml11SecurityTokenHandler != null && saml11SecurityTokenHandler.Configuration == null)
 488            {
 0489                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation(SR.Format(SR.ID4274));
 490            }
 491
 2492            if (saml2SecurityTokenHandler != null && saml2SecurityTokenHandler.Configuration == null)
 493            {
 0494                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation(SR.Format(SR.ID4274));
 495            }
 496
 497
 498            SecurityTokenAuthenticator securityTokenAuthenticator;
 2499            if (saml11SecurityTokenHandler != null && saml2SecurityTokenHandler != null)
 500            {
 501                //
 502                // Both SAML 1.1 and SAML 2.0 token handlers have been configured.
 503                //
 504
 2505                WrappedSaml11SecurityTokenAuthenticator wrappedSaml11SecurityTokenAuthenticator = new WrappedSaml11Secur
 2506                WrappedSaml2SecurityTokenAuthenticator wrappedSaml2SecurityTokenAuthenticator = new WrappedSaml2Security
 507
 2508                securityTokenAuthenticator = new WrappedSamlSecurityTokenAuthenticator(wrappedSaml11SecurityTokenAuthent
 509
 510                // The out-of-band token resolver will be used by WCF to decrypt any encrypted SAML tokens.
 2511                List<SecurityTokenResolver> resolvers = new List<SecurityTokenResolver>
 2512                {
 2513                    saml11SecurityTokenHandler.Configuration.ServiceTokenResolver,
 2514                    saml2SecurityTokenHandler.Configuration.ServiceTokenResolver
 2515                };
 2516                outOfBandTokenResolver = new AggregateTokenResolver(resolvers);
 517            }
 0518            else if (saml11SecurityTokenHandler == null && saml2SecurityTokenHandler != null)
 519            {
 520                //
 521                // SAML 1.1 token handler is not present but SAML 2.0 is. Set the token type to SAML 2.0
 522                //
 523
 0524                securityTokenAuthenticator = new WrappedSaml2SecurityTokenAuthenticator(saml2SecurityTokenHandler, _exce
 525
 526                // The out-of-band token resolver will be used by WCF to decrypt any encrypted SAML tokens.
 0527                outOfBandTokenResolver = saml2SecurityTokenHandler.Configuration.ServiceTokenResolver;
 528            }
 0529            else if (saml11SecurityTokenHandler != null && saml2SecurityTokenHandler == null)
 530            {
 531                //
 532                // SAML 1.1 token handler is present but SAML 2.0 is not. Set the token type to SAML 1.1
 533                //
 534
 0535                securityTokenAuthenticator = new WrappedSaml11SecurityTokenAuthenticator(saml11SecurityTokenHandler, _ex
 536
 537                // The out-of-band token resolver will be used by WCF to decrypt any encrypted SAML tokens.
 0538                outOfBandTokenResolver = saml11SecurityTokenHandler.Configuration.ServiceTokenResolver;
 539            }
 540            else
 541            {
 0542                securityTokenAuthenticator = CreateInnerSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenR
 543            }
 544
 2545            return securityTokenAuthenticator;
 546        }
 547
 548        /// <summary>
 549        /// Converts the ListenUri in the <see cref="SecurityTokenRequirement"/> to a normalized string.
 550        /// The method preserves the Uri scheme, port and absolute path and replaces the host name
 551        /// with the string 'NormalizedHostName'.
 552        /// </summary>
 553        /// <param name="tokenRequirement">The <see cref="SecurityTokenRequirement"/> which contains the 'ListenUri' pro
 554        /// <returns>A string representing the Normalized URI string.</returns>
 555        public static string GetNormalizedEndpointId(SecurityTokenRequirement tokenRequirement)
 556        {
 0557            if (tokenRequirement == null)
 558            {
 0559                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(tokenRequirement));
 560            }
 561
 0562            Uri listenUri = null;
 0563            if (tokenRequirement.Properties.ContainsKey(s_listenUriProperty))
 564            {
 0565                listenUri = tokenRequirement.Properties[s_listenUriProperty] as Uri;
 566            }
 567
 0568            if (listenUri == null)
 569            {
 0570                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInvalidOperation(SR.Format(SR.ID4287, tokenRequireme
 571            }
 572
 0573            if (listenUri.IsDefaultPort)
 574            {
 0575                return string.Format(CultureInfo.InvariantCulture, "{0}://NormalizedHostName{1}", listenUri.Scheme, list
 576            }
 577            else
 578            {
 0579                return string.Format(CultureInfo.InvariantCulture, "{0}://NormalizedHostName:{1}{2}", listenUri.Scheme, 
 580            }
 581        }
 582    }
 583
 584}