SecurityTokenAuthenticator CreateSpnegoSecurityTokenAuthenticator(RecipientServiceModelSecurityTokenRequirement recipientRequirement, out SecurityTokenResolver sctResolver)
        {
            SecurityBindingElement securityBindingElement = recipientRequirement.SecurityBindingElement;

            if (securityBindingElement == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.TokenAuthenticatorRequiresSecurityBindingElement, recipientRequirement));
            }
            bool isCookieMode = !recipientRequirement.SupportSecurityContextCancellation;
            LocalServiceSecuritySettings localServiceSettings = securityBindingElement.LocalServiceSettings;

            sctResolver = new SecurityContextSecurityTokenResolver(localServiceSettings.MaxCachedCookies, true);
            ExtendedProtectionPolicy extendedProtectionPolicy = null;

            recipientRequirement.TryGetProperty <ExtendedProtectionPolicy>(ServiceModelSecurityTokenRequirement.ExtendedProtectionPolicy, out extendedProtectionPolicy);

            SpnegoTokenAuthenticator authenticator = new SpnegoTokenAuthenticator();

            authenticator.ExtendedProtectionPolicy        = extendedProtectionPolicy;
            authenticator.AllowUnauthenticatedCallers     = parent.WindowsAuthentication.AllowAnonymousLogons;
            authenticator.ExtractGroupsForWindowsAccounts = parent.WindowsAuthentication.IncludeWindowsGroups;
            authenticator.IsClientAnonymous             = false;
            authenticator.EncryptStateInServiceToken    = isCookieMode;
            authenticator.IssuedSecurityTokenParameters = recipientRequirement.GetProperty <SecurityTokenParameters>(ServiceModelSecurityTokenRequirement.IssuedSecurityTokenParametersProperty);
            authenticator.IssuedTokenCache       = (ISecurityContextSecurityTokenCache)sctResolver;
            authenticator.IssuerBindingContext   = recipientRequirement.GetProperty <BindingContext>(ServiceModelSecurityTokenRequirement.IssuerBindingContextProperty);
            authenticator.ListenUri              = recipientRequirement.ListenUri;
            authenticator.SecurityAlgorithmSuite = recipientRequirement.SecurityAlgorithmSuite;
            authenticator.StandardsManager       = SecurityUtils.CreateSecurityStandardsManager(recipientRequirement, this);
            authenticator.SecurityStateEncoder   = parent.SecureConversationAuthentication.SecurityStateEncoder;
            authenticator.KnownTypes             = parent.SecureConversationAuthentication.SecurityContextClaimTypes;
            // if the SPNEGO is being done in mixed-mode, the nego blobs are from an anonymous client and so there size bound needs to be enforced.
            if (securityBindingElement is TransportSecurityBindingElement)
            {
                authenticator.MaxMessageSize = SecurityUtils.GetMaxNegotiationBufferSize(authenticator.IssuerBindingContext);
            }

            // local security quotas
            authenticator.MaximumCachedNegotiationState = localServiceSettings.MaxStatefulNegotiations;
            authenticator.NegotiationTimeout            = localServiceSettings.NegotiationTimeout;
            authenticator.ServiceTokenLifetime          = localServiceSettings.IssuedCookieLifetime;
            authenticator.MaximumConcurrentNegotiations = localServiceSettings.MaxStatefulNegotiations;

            // audit settings
            authenticator.AuditLogLocation                = recipientRequirement.AuditLogLocation;
            authenticator.SuppressAuditFailure            = recipientRequirement.SuppressAuditFailure;
            authenticator.MessageAuthenticationAuditLevel = recipientRequirement.MessageAuthenticationAuditLevel;
            return(authenticator);
        }