public Task <MessageProtections?> ProcessOutgoingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken)
        {
            var extendableMessage = message as IProtocolMessageWithExtensions;

            if (extendableMessage != null)
            {
                Protocol          protocol = Protocol.Lookup(message.Version);
                MessageDictionary baseMessageDictionary = this.Channel.MessageDescriptions.GetAccessor(message);

                // We have a helper class that will do all the heavy-lifting of organizing
                // all the extensions, their aliases, and their parameters.
                var extensionManager = ExtensionArgumentsManager.CreateOutgoingExtensions(protocol);
                foreach (IExtensionMessage protocolExtension in extendableMessage.Extensions)
                {
                    var extension = protocolExtension as IOpenIdMessageExtension;
                    if (extension != null)
                    {
                        Reporting.RecordFeatureUse(protocolExtension);

                        // Give extensions that require custom serialization a chance to do their work.
                        var customSerializingExtension = extension as IMessageWithEvents;
                        if (customSerializingExtension != null)
                        {
                            customSerializingExtension.OnSending();
                        }

                        // OpenID 2.0 Section 12 forbids two extensions with the same TypeURI in the same message.
                        ErrorUtilities.VerifyProtocol(!extensionManager.ContainsExtension(extension.TypeUri), OpenIdStrings.ExtensionAlreadyAddedWithSameTypeURI, extension.TypeUri);

                        // Ensure that we're sending out a valid extension.
                        var extensionDescription = this.Channel.MessageDescriptions.Get(extension);
                        var extensionDictionary  = extensionDescription.GetDictionary(extension).Serialize();
                        extensionDescription.EnsureMessagePartsPassBasicValidation(extensionDictionary);

                        // Add the extension to the outgoing message payload.
                        extensionManager.AddExtensionArguments(extension.TypeUri, extensionDictionary);
                    }
                    else
                    {
                        Logger.OpenId.WarnFormat("Unexpected extension type {0} did not implement {1}.", protocolExtension.GetType(), typeof(IOpenIdMessageExtension).Name);
                    }
                }

                // We use a cheap trick (for now at least) to determine whether the 'openid.' prefix
                // belongs on the parameters by just looking at what other parameters do.
                // Technically, direct message responses from Provider to Relying Party are the only
                // messages that leave off the 'openid.' prefix.
                bool includeOpenIdPrefix = baseMessageDictionary.Keys.Any(key => key.StartsWith(protocol.openid.Prefix, StringComparison.Ordinal));

                // Add the extension parameters to the base message for transmission.
                baseMessageDictionary.AddExtraParameters(extensionManager.GetArgumentsToSend(includeOpenIdPrefix));
                return(NoneTask);
            }

            return(NullTask);
        }