protected override IProtocolMessage RequestCore(IDirectedProtocolMessage request) { this.ProcessMessageFilter(request, true); // Drop the outgoing message in the other channel's in-slot and let them know it's there. this.RemoteChannel.PostMessage(request); // Now wait for a response... MessageReceivingEndpoint recipient; WebHeaderCollection headers; IDictionary <string, string> responseData = this.AwaitIncomingMessage(out recipient, out headers); ErrorUtilities.VerifyInternal(recipient == null, "The recipient is expected to be null for direct responses."); // And deserialize it. IDirectResponseProtocolMessage responseMessage = this.MessageFactory.GetNewResponseMessage(request, responseData); if (responseMessage == null) { return(null); } var responseAccessor = this.MessageDescriptions.GetAccessor(responseMessage); responseAccessor.Deserialize(responseData); var responseMessageHttpRequest = responseMessage as IHttpDirectRequest; if (headers != null && responseMessageHttpRequest != null) { headers.ApplyTo(responseMessageHttpRequest.Headers); } this.ProcessMessageFilter(responseMessage, false); return(responseMessage); }
/// <summary> /// Submits a direct request message to some remote party and blocks waiting for an immediately reply. /// </summary> /// <param name="request">The request message.</param> /// <returns>The response message, or null if the response did not carry a message.</returns> /// <remarks> /// Typically a deriving channel will override <see cref="CreateHttpRequest"/> to customize this method's /// behavior. However in non-HTTP frameworks, such as unit test mocks, it may be appropriate to override /// this method to eliminate all use of an HTTP transport. /// </remarks> protected virtual IProtocolMessage RequestInternal(IDirectedProtocolMessage request) { HttpWebRequest webRequest = this.CreateHttpRequest(request); IDictionary <string, string> responseFields; using (DirectWebResponse response = this.GetDirectResponse(webRequest)) { if (response.ResponseStream == null) { return(null); } responseFields = this.ReadFromResponseInternal(response); } IDirectResponseProtocolMessage responseMessage = this.MessageFactory.GetNewResponseMessage(request, responseFields); if (responseMessage == null) { return(null); } var responseSerializer = MessageSerializer.Get(responseMessage.GetType()); responseSerializer.Deserialize(responseFields, responseMessage); return(responseMessage); }
/// <summary> /// Initializes a new instance of the <see cref="ProtocolFaultResponseException"/> class /// such that it can be sent as a protocol message response to a remote caller. /// </summary> /// <param name="channel">The channel to use when encoding the response message.</param> /// <param name="errorResponse">The message to send back to the HTTP client.</param> /// <param name="faultedMessage">The message that was the cause of the exception. May be null.</param> /// <param name="innerException">The inner exception.</param> /// <param name="message">The message for the exception.</param> protected internal ProtocolFaultResponseException(Channel channel, IDirectResponseProtocolMessage errorResponse, IProtocolMessage faultedMessage = null, Exception innerException = null, string message = null) : base(message ?? (innerException != null ? innerException.Message : null), faultedMessage, innerException) { Requires.NotNull(channel, "channel"); Requires.NotNull(errorResponse, "errorResponse"); this.channel = channel; this.ErrorResponseMessage = errorResponse; }
public void SingleResponseMessageType() { this.factory.AddMessageTypes(new MessageDescription[] { MessageDescriptions.Get(typeof(DirectResponseMessageMock), V1) }); var fields = new Dictionary <string, string> { { "random", "bits" }, }; IDirectedProtocolMessage request = new RequestMessageMock(receiver.Location, V1); Assert.IsNull(this.factory.GetNewResponseMessage(request, fields)); fields["Age"] = "18"; IDirectResponseProtocolMessage response = this.factory.GetNewResponseMessage(request, fields); Assert.IsInstanceOf <DirectResponseMessageMock>(response); Assert.AreSame(request, response.OriginatingRequest); // Verify that we can instantiate a response with a derived-type of an expected request message. request = new TestSignedDirectedMessage(); response = this.factory.GetNewResponseMessage(request, fields); Assert.IsInstanceOf <DirectResponseMessageMock>(response); Assert.AreSame(request, response.OriginatingRequest); }
/// <summary> /// Called when receiving a direct response message, before deserialization begins. /// </summary> /// <param name="response">The HTTP direct response.</param> /// <param name="message">The newly instantiated message, prior to deserialization.</param> protected override void OnReceivingDirectResponse(HttpResponseMessage response, IDirectResponseProtocolMessage message) { base.OnReceivingDirectResponse(response, message); // Verify that the expected HTTP status code was used for the message, // per OpenID 2.0 section 5.1.2.2. // Note: The v1.1 spec doesn't require 400 responses for some error messages if (message.Version.Major >= 2) { var httpDirectResponse = message as IHttpDirectResponse; if (httpDirectResponse != null) { ErrorUtilities.VerifyProtocol( httpDirectResponse.HttpStatusCode == response.StatusCode, MessagingStrings.UnexpectedHttpStatusCode, (int)httpDirectResponse.HttpStatusCode, (int)response.StatusCode); } } }
/// <summary> /// Checks the incoming HTTP request for an access token request and prepares a response if the request message was found. /// </summary> /// <param name="httpRequestInfo">The HTTP request info.</param> /// <param name="response">The formulated response, or <c>null</c> if the request was not found..</param> /// <returns>A value indicating whether any access token request was found in the HTTP request.</returns> /// <remarks> /// This method assumes that the authorization server and the resource server are the same and that they share a single /// asymmetric key for signing and encrypting the access token. If this is not true, use the <see cref="ReadAccessTokenRequest"/> method instead. /// </remarks> public bool TryPrepareAccessTokenResponse(HttpRequestInfo httpRequestInfo, out IDirectResponseProtocolMessage response) { Contract.Requires<ArgumentNullException>(httpRequestInfo != null); Contract.Ensures(Contract.Result<bool>() == (Contract.ValueAtReturn<IDirectResponseProtocolMessage>(out response) != null)); var request = this.ReadAccessTokenRequest(httpRequestInfo); if (request != null) { response = this.PrepareAccessTokenResponse(request); return true; } response = null; return false; }
/// <summary> /// Checks the incoming HTTP request for an access token request and prepares a response if the request message was found. /// </summary> /// <param name="response">The formulated response, or <c>null</c> if the request was not found..</param> /// <returns>A value indicating whether any access token request was found in the HTTP request.</returns> /// <remarks> /// This method assumes that the authorization server and the resource server are the same and that they share a single /// asymmetric key for signing and encrypting the access token. If this is not true, use the <see cref="ReadAccessTokenRequest"/> method instead. /// </remarks> public bool TryPrepareAccessTokenResponse(out IDirectResponseProtocolMessage response) { return this.TryPrepareAccessTokenResponse(this.Channel.GetRequestFromContext(), out response); }
protected virtual void OnReceivingDirectResponse(HttpResponseMessage response, IDirectResponseProtocolMessage message) { }
/// <summary> /// Called when receiving a direct response message, before deserialization begins. /// </summary> /// <param name="response">The HTTP direct response.</param> /// <param name="message">The newly instantiated message, prior to deserialization.</param> protected override void OnReceivingDirectResponse(IncomingWebResponse response, IDirectResponseProtocolMessage message) { base.OnReceivingDirectResponse(response, message); // Verify that the expected HTTP status code was used for the message, // per OpenID 2.0 section 5.1.2.2. // Note: The v1.1 spec doesn't require 400 responses for some error messages if (message.Version.Major >= 2) { var httpDirectResponse = message as IHttpDirectResponse; if (httpDirectResponse != null) { ErrorUtilities.VerifyProtocol( httpDirectResponse.HttpStatusCode == response.Status, MessagingStrings.UnexpectedHttpStatusCode, (int)httpDirectResponse.HttpStatusCode, (int)response.Status); } } }
/// <summary> /// Checks the incoming HTTP request for an access token request and prepares a response if the request message was found. /// </summary> /// <param name="httpRequestInfo">The HTTP request info.</param> /// <param name="response">The formulated response, or <c>null</c> if the request was not found..</param> /// <returns>A value indicating whether any access token request was found in the HTTP request.</returns> /// <remarks> /// This method assumes that the authorization server and the resource server are the same and that they share a single /// asymmetric key for signing and encrypting the access token. If this is not true, use the <see cref="ReadAccessTokenRequest"/> method instead. /// </remarks> public bool TryPrepareAccessTokenResponse(HttpRequestInfo httpRequestInfo, out IDirectResponseProtocolMessage response) { Contract.Requires<ArgumentNullException>(httpRequestInfo != null); Contract.Ensures(Contract.Result<bool>() == (Contract.ValueAtReturn<IDirectResponseProtocolMessage>(out response) != null)); var request = this.ReadAccessTokenRequest(httpRequestInfo); if (request != null) { // This convenience method only encrypts access tokens assuming that this auth server // doubles as the resource server. using (var resourceServerPublicKey = this.AuthorizationServerServices.CreateAccessTokenSigningCryptoServiceProvider()) { response = this.PrepareAccessTokenResponse(request, resourceServerPublicKey); } return true; } response = null; return false; }
/// <summary> /// Determines whether the specified message is a direct response. /// </summary> /// <param name="message">The message in question.</param> /// <returns> /// <c>true</c> if the specified message is a direct response; otherwise, <c>false</c>. /// </returns> /// <remarks> /// Although an <see cref="IProtocolMessage"/> may implement the /// <see cref="IDirectResponseProtocolMessage"/> interface, it may only be doing /// that for its derived classes. These objects are only requests if their /// <see cref="IDirectResponseProtocolMessage.OriginatingRequest"/> property is non-null. /// </remarks> internal static bool IsDirectResponse(this IDirectResponseProtocolMessage message) { ErrorUtilities.VerifyArgumentNotNull(message, "message"); return(message.OriginatingRequest != null); }
/// <summary> /// Determines whether the specified message is a direct response. /// </summary> /// <param name="message">The message in question.</param> /// <returns> /// <c>true</c> if the specified message is a direct response; otherwise, <c>false</c>. /// </returns> /// <remarks> /// Although an <see cref="IProtocolMessage"/> may implement the /// <see cref="IDirectResponseProtocolMessage"/> interface, it may only be doing /// that for its derived classes. These objects are only requests if their /// <see cref="IDirectResponseProtocolMessage.OriginatingRequest"/> property is non-null. /// </remarks> internal static bool IsDirectResponse(this IDirectResponseProtocolMessage message) { Contract.Requires <ArgumentNullException>(message != null); return(message.OriginatingRequest != null); }