Example #1
0
        /// <summary>
        /// Prepares to send a request to the Service Provider as the payload of a POST request.
        /// </summary>
        /// <param name="requestMessage">The message to be transmitted to the ServiceProvider.</param>
        /// <returns>The web request ready to send.</returns>
        /// <remarks>
        /// This method is simply a standard HTTP POST request with the message parts serialized to the POST entity
        /// with the application/x-www-form-urlencoded content type
        /// This method satisfies OAuth 1.0 section 5.2, item #2 and OpenID 2.0 section 4.1.2.
        /// </remarks>
        protected virtual HttpWebRequest InitializeRequestAsPost(IDirectedProtocolMessage requestMessage)
        {
            ErrorUtilities.VerifyArgumentNotNull(requestMessage, "requestMessage");

            var serializer = MessageSerializer.Get(requestMessage.GetType());
            var fields     = serializer.Serialize(requestMessage);

            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(requestMessage.Recipient);

            httpRequest.CachePolicy = this.CachePolicy;
            httpRequest.Method      = "POST";
            httpRequest.ContentType = "application/x-www-form-urlencoded";
            httpRequest.Headers[HttpRequestHeader.ContentEncoding] = PostEntityEncoding.WebName;
            string requestBody = MessagingUtilities.CreateQueryString(fields);

            byte[] requestBytes = PostEntityEncoding.GetBytes(requestBody);
            httpRequest.ContentLength = requestBytes.Length;
            Stream requestStream = this.WebRequestHandler.GetRequestStream(httpRequest);

            try {
                requestStream.Write(requestBytes, 0, requestBytes.Length);
            } finally {
                // We need to be sure to close the request stream...
                // unless it is a MemoryStream, which is a clue that we're in
                // a mock stream situation and closing it would preclude reading it later.
                if (!(requestStream is MemoryStream))
                {
                    requestStream.Dispose();
                }
            }

            return(httpRequest);
        }
Example #2
0
        public IProtocolMessage RequestAsync(IDirectedProtocolMessage requestMessage, CancellationToken cancellationToken)
        {
            this.ProcessOutgoingMessageAsync(requestMessage, cancellationToken);
            Logger.Channel.DebugFormat("Sending {0} request.", requestMessage.GetType().Name);
            var responseMessage = this.RequestCoreAsync(requestMessage, cancellationToken);

            ErrorUtilities.VerifyProtocol(responseMessage != null, MessagingStrings.ExpectedMessageNotReceived, typeof(IProtocolMessage).Name);
            Logger.Channel.DebugFormat("Received {0} response.", responseMessage.GetType().Name);
            this.ProcessIncomingMessageAsync(responseMessage, cancellationToken);

            return(responseMessage);
        }
Example #3
0
        /// <summary>
        /// Prepares to send a request to the Service Provider as the query string in a GET request.
        /// </summary>
        /// <param name="requestMessage">The message to be transmitted to the ServiceProvider.</param>
        /// <returns>The web request ready to send.</returns>
        /// <remarks>
        /// This method is simply a standard HTTP Get request with the message parts serialized to the query string.
        /// This method satisfies OAuth 1.0 section 5.2, item #3.
        /// </remarks>
        protected virtual HttpWebRequest InitializeRequestAsGet(IDirectedProtocolMessage requestMessage)
        {
            ErrorUtilities.VerifyArgumentNotNull(requestMessage, "requestMessage");

            var serializer = MessageSerializer.Get(requestMessage.GetType());
            var fields     = serializer.Serialize(requestMessage);

            UriBuilder builder = new UriBuilder(requestMessage.Recipient);

            MessagingUtilities.AppendQueryArgs(builder, fields);
            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(builder.Uri);

            return(httpRequest);
        }
Example #4
0
        /// <summary>
        /// Queues an indirect message for transmittal via the user agent.
        /// </summary>
        /// <param name="message">The message to send.</param>
        /// <returns>The pending user agent redirect based message to be sent as an HttpResponse.</returns>
        protected virtual UserAgentResponse SendIndirectMessage(IDirectedProtocolMessage message)
        {
            ErrorUtilities.VerifyArgumentNotNull(message, "message");

            var serializer = MessageSerializer.Get(message.GetType());
            var fields     = serializer.Serialize(message);

            // First try creating a 301 redirect, and fallback to a form POST
            // if the message is too big.
            UserAgentResponse response = this.Create301RedirectResponse(message, fields);

            if (response.Headers[HttpResponseHeader.Location].Length > indirectMessageGetToPostThreshold)
            {
                response = this.CreateFormPostResponse(message, fields);
            }

            return(response);
        }
Example #5
0
        /// <summary>
        /// HttpRequestMessage装换未IDirectedProtocolMessage
        /// </summary>
        /// <param name="httpRequest"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public IDirectedProtocolMessage ReadFromRequestAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken)
        {
            if (Logger.Channel.IsInfoEnabled() && httpRequest.RequestUri != null)
            {
                Logger.Channel.InfoFormat("Scanning incoming request for messages: {0}", httpRequest.RequestUri.AbsoluteUri);
            }
            IDirectedProtocolMessage requestMessage = this.ReadFromRequestCoreAsync(httpRequest, cancellationToken);

            if (requestMessage != null)
            {
                Logger.Channel.DebugFormat("Incoming request received: {0}", requestMessage.GetType().Name);
                var directRequest = requestMessage as IHttpDirectRequest;
                if (directRequest != null)
                {
                    foreach (var header in httpRequest.Headers)
                    {
                        directRequest.Headers.Add(header.Key, header.Value);
                    }
                }
                this.ProcessIncomingMessageAsync(requestMessage, cancellationToken);
            }
            return(requestMessage);
        }
Example #6
0
        /// <summary>
        /// Instantiates the given request message type.
        /// </summary>
        /// <param name="messageDescription">The message description.</param>
        /// <param name="request">The request that resulted in this response.</param>
        /// <returns>The instantiated message.  Never null.</returns>
        protected virtual IDirectResponseProtocolMessage InstantiateAsResponse(MessageDescription messageDescription, IDirectedProtocolMessage request)
        {
            Requires.NotNull(messageDescription, "messageDescription");
            Requires.NotNull(request, "request");

            Type            requestType = request.GetType();
            var             ctors       = this.FindMatchingResponseConstructors(messageDescription, requestType);
            ConstructorInfo ctor        = null;

            try {
                ctor = ctors.Single();
            } catch (InvalidOperationException) {
                if (ctors.Any())
                {
                    ErrorUtilities.ThrowInternal("More than one matching constructor for request type " + requestType.Name + " and response type " + messageDescription.MessageType.Name);
                }
                else
                {
                    ErrorUtilities.ThrowInternal("Unexpected request message type " + requestType.FullName + " for response type " + messageDescription.MessageType.Name);
                }
            }
            return((IDirectResponseProtocolMessage)ctor.Invoke(new object[] { request }));
        }
        /// <summary>
        /// Analyzes an incoming request message payload to discover what kind of 
        /// message is embedded in it and returns the type, or null if no match is found.
        /// </summary>
        /// <param name="request">
        /// The message that was sent as a request that resulted in the response.
        /// Null on a Consumer site that is receiving an indirect message from the Service Provider.
        /// </param>
        /// <param name="fields">The name/value pairs that make up the message payload.</param>
        /// <returns>
        /// A newly instantiated <see cref="IProtocolMessage"/>-derived object that this message can
        /// deserialize to.  Null if the request isn't recognized as a valid protocol message.
        /// </returns>
        /// <remarks>
        /// The response messages are:
        /// UnauthorizedTokenResponse
        /// AuthorizedTokenResponse
        /// </remarks>
        public virtual IDirectResponseProtocolMessage GetNewResponseMessage(IDirectedProtocolMessage request, IDictionary<string, string> fields)
        {
            ErrorUtilities.VerifyArgumentNotNull(request, "request");
            ErrorUtilities.VerifyArgumentNotNull(fields, "fields");

            MessageBase message = null;

            // All response messages have the oauth_token field.
            if (!fields.ContainsKey("oauth_token")) {
                return null;
            }

            // All direct message responses should have the oauth_token_secret field.
            if (!fields.ContainsKey("oauth_token_secret")) {
                Logger.OAuth.Error("An OAuth message was expected to contain an oauth_token_secret but didn't.");
                return null;
            }

            var unauthorizedTokenRequest = request as UnauthorizedTokenRequest;
            var authorizedTokenRequest = request as AuthorizedTokenRequest;
            if (unauthorizedTokenRequest != null) {
                Protocol protocol = fields.ContainsKey("oauth_callback_confirmed") ? Protocol.V10a : Protocol.V10;
                message = new UnauthorizedTokenResponse(unauthorizedTokenRequest, protocol.Version);
            } else if (authorizedTokenRequest != null) {
                message = new AuthorizedTokenResponse(authorizedTokenRequest);
            } else {
                Logger.OAuth.ErrorFormat("Unexpected response message given the request type {0}", request.GetType().Name);
                throw new ProtocolException(OAuthStrings.InvalidIncomingMessage);
            }

            if (message != null) {
                message.SetAsIncoming();
            }

            return message;
        }
        /// <summary>
        /// Analyzes an incoming request message payload to discover what kind of
        /// message is embedded in it and returns the type, or null if no match is found.
        /// </summary>
        /// <param name="request">
        /// The message that was sent as a request that resulted in the response.
        /// Null on a Consumer site that is receiving an indirect message from the Service Provider.
        /// </param>
        /// <param name="fields">The name/value pairs that make up the message payload.</param>
        /// <returns>
        /// A newly instantiated <see cref="IProtocolMessage"/>-derived object that this message can
        /// deserialize to.  Null if the request isn't recognized as a valid protocol message.
        /// </returns>
        /// <remarks>
        /// The response messages are:
        /// UnauthorizedTokenResponse
        /// AuthorizedTokenResponse
        /// </remarks>
        public virtual IDirectResponseProtocolMessage GetNewResponseMessage(IDirectedProtocolMessage request, IDictionary <string, string> fields)
        {
            MessageBase message = null;

            // All response messages have the oauth_token field.
            if (!fields.ContainsKey("oauth_token"))
            {
                return(null);
            }

            // All direct message responses should have the oauth_token_secret field.
            if (!fields.ContainsKey("oauth_token_secret"))
            {
                Logger.OAuth.Error("An OAuth message was expected to contain an oauth_token_secret but didn't.");
                return(null);
            }

            var unauthorizedTokenRequest = request as UnauthorizedTokenRequest;
            var authorizedTokenRequest   = request as AuthorizedTokenRequest;

            if (unauthorizedTokenRequest != null)
            {
                Protocol protocol = fields.ContainsKey("oauth_callback_confirmed") ? Protocol.V10a : Protocol.V10;
                message = new UnauthorizedTokenResponse(unauthorizedTokenRequest, protocol.Version);
            }
            else if (authorizedTokenRequest != null)
            {
                message = new AuthorizedTokenResponse(authorizedTokenRequest);
            }
            else
            {
                Logger.OAuth.ErrorFormat("Unexpected response message given the request type {0}", request.GetType().Name);
                throw new ProtocolException(OAuthStrings.InvalidIncomingMessage);
            }

            if (message != null)
            {
                message.SetAsIncoming();
            }

            return(message);
        }
        /// <summary>
        /// Gets the message type that best fits the given incoming direct response data.
        /// </summary>
        /// <param name="request">The request message that prompted the response data.</param>
        /// <param name="fields">The data of the incoming message.</param>
        /// <returns>
        /// The message type that matches the incoming data; or <c>null</c> if no match.
        /// </returns>
        /// <exception cref="ProtocolException">May be thrown if the incoming data is ambiguous.</exception>
        protected virtual MessageDescription GetMessageDescription(IDirectedProtocolMessage request, IDictionary <string, string> fields)
        {
            Requires.NotNull(request, "request");
            Requires.NotNull(fields, "fields");

            var matches = (from responseMessageType in this.responseMessageTypes
                           let message = responseMessageType.Key
                                         where message.CheckMessagePartsPassBasicValidation(fields)
                                         let ctors = this.FindMatchingResponseConstructors(message, request.GetType())
                                                     where ctors.Any()
                                                     orderby GetDerivationDistance(ctors.First().GetParameters()[0].ParameterType, request.GetType()),
                           CountInCommon(message.Mapping.Keys, fields.Keys) descending,
                           message.Mapping.Count descending
                           select message).CacheGeneratedResults();
            var match = matches.FirstOrDefault();

            if (match != null)
            {
                return(match);
            }
            else
            {
                // No message type matches the incoming data.
                return(null);
            }
        }
        /// <summary>
        /// Prepares an HTTP request that carries a given message.
        /// </summary>
        /// <param name="request">The message to send.</param>
        /// <returns>
        /// The <see cref="HttpRequest"/> prepared to send the request.
        /// </returns>
        protected override HttpWebRequest CreateHttpRequest(IDirectedProtocolMessage request)
        {
            ErrorUtilities.VerifyArgumentNotNull(request, "request");
            ErrorUtilities.VerifyArgumentNamed(request.Recipient != null, "request", MessagingStrings.DirectedMessageMissingRecipient);

            IDirectedProtocolMessage oauthRequest = request as IDirectedProtocolMessage;

            ErrorUtilities.VerifyArgument(oauthRequest != null, MessagingStrings.UnexpectedType, typeof(IDirectedProtocolMessage), request.GetType());

            HttpWebRequest httpRequest;

            HttpDeliveryMethods transmissionMethod = oauthRequest.HttpMethods;

            if ((transmissionMethod & HttpDeliveryMethods.AuthorizationHeaderRequest) != 0)
            {
                httpRequest = this.InitializeRequestAsAuthHeader(request);
            }
            else if ((transmissionMethod & HttpDeliveryMethods.PostRequest) != 0)
            {
                httpRequest = this.InitializeRequestAsPost(request);
            }
            else if ((transmissionMethod & HttpDeliveryMethods.GetRequest) != 0)
            {
                httpRequest = InitializeRequestAsGet(request);
            }
            else
            {
                throw new NotSupportedException();
            }
            return(httpRequest);
        }
Example #11
0
        /// <summary>
        /// Prepares an HTTP request that carries a given message.
        /// </summary>
        /// <param name="request">The message to send.</param>
        /// <returns>
        /// The <see cref="HttpRequest"/> prepared to send the request.
        /// </returns>
        protected override HttpWebRequest CreateHttpRequest(IDirectedProtocolMessage request)
        {
            ErrorUtilities.VerifyArgumentNotNull(request, "request");
            ErrorUtilities.VerifyArgumentNamed(request.Recipient != null, "request", MessagingStrings.DirectedMessageMissingRecipient);

            IDirectedProtocolMessage oauthRequest = request as IDirectedProtocolMessage;
            ErrorUtilities.VerifyArgument(oauthRequest != null, MessagingStrings.UnexpectedType, typeof(IDirectedProtocolMessage), request.GetType());

            HttpWebRequest httpRequest;

            HttpDeliveryMethods transmissionMethod = oauthRequest.HttpMethods;
            if ((transmissionMethod & HttpDeliveryMethods.AuthorizationHeaderRequest) != 0) {
                httpRequest = this.InitializeRequestAsAuthHeader(request);
            } else if ((transmissionMethod & HttpDeliveryMethods.PostRequest) != 0) {
                httpRequest = this.InitializeRequestAsPost(request);
            } else if ((transmissionMethod & HttpDeliveryMethods.GetRequest) != 0) {
                httpRequest = InitializeRequestAsGet(request);
            } else {
                throw new NotSupportedException();
            }
            return httpRequest;
        }
        public static bool TryReadFromRequest <TRequest>(this Channel chan, Request httpRequest, out TRequest request)
            where TRequest : class, IProtocolMessage
        {
            if (httpRequest == null)
            {
                throw new ArgumentNullException("httpRequest");
            }
            Contract.Ensures(Contract.Result <bool>() == (Contract.ValueAtReturn <TRequest>(out request) != null));

            IProtocolMessage untypedRequest = null;

            if (Logger.IsInfoEnabled && httpRequest.Url != null)
            {
                Logger.InfoFormat("Scanning incoming request for messages: {0}", httpRequest.Url.ToString());
            }
            IDirectedProtocolMessage requestMessage = null;

            Contract.Assume(httpRequest.Form != null && httpRequest.Query != null);
            var fields = httpRequest.Form.ToDictionary();

            if (fields.Count == 0 && httpRequest.Method != "POST")   // OpenID 2.0 section 4.1.2
            {
                fields = ((IDictionary <string, object>)(DynamicDictionary) httpRequest.Query).ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToString());
            }

            MessageReceivingEndpoint recipient = null;

            try {
                HttpDeliveryMethods method;
                Enum.TryParse <HttpDeliveryMethods>(httpRequest.Method + "Request", true, out method);
                recipient = new MessageReceivingEndpoint(httpRequest.Url.SiteBase, method);
            } catch (ArgumentException ex) {
                Logger.WarnFormat("Unrecognized HTTP request: {0}", ex);
                requestMessage = null;
            }

            if (recipient != null)
            {
                requestMessage = (IDirectedProtocolMessage)Receive(chan, fields, recipient);
            }

            if (requestMessage != null)
            {
                Logger.DebugFormat("Incoming request received: {0}", requestMessage.GetType().Name);

                var directRequest = requestMessage as IHttpDirectRequest;
                if (directRequest != null)
                {
                    foreach (string header in httpRequest.Headers.Keys)
                    {
                        directRequest.Headers[header] = httpRequest.Headers[header].ToString();
                    }
                }

                ProcessIncomingMessage(chan, requestMessage);
                untypedRequest = requestMessage;
            }

            if (untypedRequest == null)
            {
                request = null;
                return(false);
            }

            request = untypedRequest as TRequest;

            return(true);
        }
		/// <summary>
		/// Instantiates the given request message type.
		/// </summary>
		/// <param name="messageDescription">The message description.</param>
		/// <param name="request">The request that resulted in this response.</param>
		/// <returns>The instantiated message.  Never null.</returns>
		protected virtual IDirectResponseProtocolMessage InstantiateAsResponse(MessageDescription messageDescription, IDirectedProtocolMessage request) {
			Contract.Requires<ArgumentNullException>(messageDescription != null);
			Contract.Requires<ArgumentNullException>(request != null);
			Contract.Ensures(Contract.Result<IDirectResponseProtocolMessage>() != null);

			Type requestType = request.GetType();
			var ctors = this.FindMatchingResponseConstructors(messageDescription, requestType);
			ConstructorInfo ctor = null;
			try {
				ctor = ctors.Single();
			} catch (InvalidOperationException) {
				if (ctors.Any()) {
					ErrorUtilities.ThrowInternal("More than one matching constructor for request type " + requestType.Name + " and response type " + messageDescription.MessageType.Name);
				} else {
					ErrorUtilities.ThrowInternal("Unexpected request message type " + requestType.FullName + " for response type " + messageDescription.MessageType.Name);
				}
			}
			return (IDirectResponseProtocolMessage)ctor.Invoke(new object[] { request });
		}
		/// <summary>
		/// Gets the message type that best fits the given incoming direct response data.
		/// </summary>
		/// <param name="request">The request message that prompted the response data.</param>
		/// <param name="fields">The data of the incoming message.</param>
		/// <returns>
		/// The message type that matches the incoming data; or <c>null</c> if no match.
		/// </returns>
		/// <exception cref="ProtocolException">May be thrown if the incoming data is ambiguous.</exception>
		protected virtual MessageDescription GetMessageDescription(IDirectedProtocolMessage request, IDictionary<string, string> fields) {
			Contract.Requires<ArgumentNullException>(request != null);
			Contract.Requires<ArgumentNullException>(fields != null);

			var matches = (from responseMessageType in this.responseMessageTypes
			               let message = responseMessageType.Key
			               where message.CheckMessagePartsPassBasicValidation(fields)
			               let ctors = this.FindMatchingResponseConstructors(message, request.GetType())
			               where ctors.Any()
			               orderby GetDerivationDistance(ctors.First().GetParameters()[0].ParameterType, request.GetType()),
			                 CountInCommon(message.Mapping.Keys, fields.Keys) descending,
			                 message.Mapping.Count descending
			               select message).CacheGeneratedResults();
			var match = matches.FirstOrDefault();
			if (match != null) {
				if (Logger.Messaging.IsWarnEnabled && matches.Count() > 1) {
					Logger.Messaging.WarnFormat(
						"Multiple message types seemed to fit the incoming data: {0}",
						matches.ToStringDeferred());
				}

				return match;
			} else {
				// No message type matches the incoming data.
				return null;
			}
		}
        protected virtual MessageDescription GetMessageDescription(IDirectedProtocolMessage request, IDictionary <string, string> fields)
        {
            var matches = (from responseMessageType in this.responseMessageTypes
                           let messge = responseMessageType.Key
                                        where messge.CheckMessagePartsPassBasicValidation(fields)
                                        let ctors = this.FindMatchingResponseConstructors(messge, request.GetType())
                                                    where ctors.Any()
                                                    orderby GetDerivationDistance(ctors.First().GetParameters()[0].ParameterType, request.GetType()),
                           CountInCommon(messge.Mapping.Keys, fields.Keys) descending,
                           messge.Mapping.Count descending
                           select messge).CacheGeneratedResults();
            var match = matches.FirstOrDefault();

            if (match != null)
            {
                if (Logger.Messaging.IsWarnEnabled() && matches.Count() > 1)
                {
                    Logger.Messaging.WarnFormat(
                        "Multiple message types seemed to fit the incoming data: {0}",
                        matches.ToStringDeferred());
                }

                return(match);
            }
            else
            {
                return(null);
            }
        }