summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2013-03-26 11:19:06 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2013-03-26 11:19:06 -0700
commit3d37ff45cab6838d80b22e6b782a0b9b4c2f4aeb (patch)
treec15816c3d7f6e74334553f2ff98605ce1c22c538 /src/DotNetOpenAuth.OpenId/OpenId/ChannelElements
parent5e9014f36b2d53b8e419918675df636540ea24e2 (diff)
parente6f7409f4caceb7bc2a5b4ddbcb1a4097af340f2 (diff)
downloadDotNetOpenAuth-3d37ff45cab6838d80b22e6b782a0b9b4c2f4aeb.zip
DotNetOpenAuth-3d37ff45cab6838d80b22e6b782a0b9b4c2f4aeb.tar.gz
DotNetOpenAuth-3d37ff45cab6838d80b22e6b782a0b9b4c2f4aeb.tar.bz2
Move to HttpClient throughout library.
Diffstat (limited to 'src/DotNetOpenAuth.OpenId/OpenId/ChannelElements')
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/BackwardCompatibilityBindingElement.cs27
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ExtensionsBindingElement.cs27
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/KeyValueFormEncoding.cs7
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs130
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ReturnToSignatureBindingElement.cs27
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SigningBindingElement.cs20
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SkipSecurityBindingElement.cs17
7 files changed, 178 insertions, 77 deletions
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/BackwardCompatibilityBindingElement.cs b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/BackwardCompatibilityBindingElement.cs
index ff8a766..4c55360 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/BackwardCompatibilityBindingElement.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/BackwardCompatibilityBindingElement.cs
@@ -6,6 +6,8 @@
namespace DotNetOpenAuth.OpenId.ChannelElements {
using System;
+ using System.Threading;
+ using System.Threading.Tasks;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OpenId.Messages;
@@ -17,6 +19,17 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// </summary>
internal class BackwardCompatibilityBindingElement : IChannelBindingElement {
/// <summary>
+ /// A reusable pre-completed task that may be returned multiple times to reduce GC pressure.
+ /// </summary>
+ private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+
+ /// <summary>
+ /// A reusable pre-completed task that may be returned multiple times to reduce GC pressure.
+ /// </summary>
+ private static readonly Task<MessageProtections?> NoneTask =
+ Task.FromResult<MessageProtections?>(MessageProtections.None);
+
+ /// <summary>
/// The "dnoa.op_endpoint" callback parameter that stores the Provider Endpoint URL
/// to tack onto the return_to URI.
/// </summary>
@@ -51,6 +64,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Prepares a message for sending based on the rules of this channel binding element.
/// </summary>
/// <param name="message">The message to prepare for sending.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The protections (if any) that this binding element applied to the message.
/// Null if this binding element did not even apply to this binding element.
@@ -59,7 +73,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Implementations that provide message protection must honor the
/// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
/// </remarks>
- public MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) {
+ public Task<MessageProtections?> ProcessOutgoingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
SignedResponseRequest request = message as SignedResponseRequest;
if (request != null && request.Version.Major < 2) {
request.AddReturnToArguments(ProviderEndpointParameterName, request.Recipient.AbsoluteUri);
@@ -69,10 +83,10 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
request.AddReturnToArguments(ClaimedIdentifierParameterName, authRequest.ClaimedIdentifier);
}
- return MessageProtections.None;
+ return NoneTask;
}
- return null;
+ return NullTask;
}
/// <summary>
@@ -80,6 +94,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// validates an incoming message based on the rules of this channel binding element.
/// </summary>
/// <param name="message">The incoming message to process.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The protections (if any) that this binding element applied to the message.
/// Null if this binding element did not even apply to this binding element.
@@ -92,7 +107,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Implementations that provide message protection must honor the
/// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
/// </remarks>
- public MessageProtections? ProcessIncomingMessage(IProtocolMessage message) {
+ public Task<MessageProtections?> ProcessIncomingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
IndirectSignedResponse response = message as IndirectSignedResponse;
if (response != null && response.Version.Major < 2) {
// GetReturnToArgument may return parameters that are not signed,
@@ -118,10 +133,10 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
}
}
- return MessageProtections.None;
+ return NoneTask;
}
- return null;
+ return NullTask;
}
#endregion
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ExtensionsBindingElement.cs b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ExtensionsBindingElement.cs
index f24c8b4..727dad7 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ExtensionsBindingElement.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ExtensionsBindingElement.cs
@@ -10,6 +10,8 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
+ using System.Threading;
+ using System.Threading.Tasks;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OpenId.Extensions;
@@ -22,6 +24,17 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// </summary>
internal class ExtensionsBindingElement : IChannelBindingElement {
/// <summary>
+ /// A reusable pre-completed task that may be returned multiple times to reduce GC pressure.
+ /// </summary>
+ private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+
+ /// <summary>
+ /// A reusable pre-completed task that may be returned multiple times to reduce GC pressure.
+ /// </summary>
+ private static readonly Task<MessageProtections?> NoneTask =
+ Task.FromResult<MessageProtections?>(MessageProtections.None);
+
+ /// <summary>
/// False if unsigned extensions should be dropped. Must always be true on Providers, since RPs never sign extensions.
/// </summary>
private readonly bool receiveUnsignedExtensions;
@@ -68,6 +81,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Prepares a message for sending based on the rules of this channel binding element.
/// </summary>
/// <param name="message">The message to prepare for sending.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The protections (if any) that this binding element applied to the message.
/// Null if this binding element did not even apply to this binding element.
@@ -77,7 +91,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
/// </remarks>
[SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "It doesn't look too bad to me. :)")]
- public MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) {
+ public Task<MessageProtections?> ProcessOutgoingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
var extendableMessage = message as IProtocolMessageWithExtensions;
if (extendableMessage != null) {
Protocol protocol = Protocol.Lookup(message.Version);
@@ -120,10 +134,10 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
// Add the extension parameters to the base message for transmission.
baseMessageDictionary.AddExtraParameters(extensionManager.GetArgumentsToSend(includeOpenIdPrefix));
- return MessageProtections.None;
+ return NoneTask;
}
- return null;
+ return NullTask;
}
/// <summary>
@@ -131,6 +145,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// validates an incoming message based on the rules of this channel binding element.
/// </summary>
/// <param name="message">The incoming message to process.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The protections (if any) that this binding element applied to the message.
/// Null if this binding element did not even apply to this binding element.
@@ -143,7 +158,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Implementations that provide message protection must honor the
/// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
/// </remarks>
- public MessageProtections? ProcessIncomingMessage(IProtocolMessage message) {
+ public Task<MessageProtections?> ProcessIncomingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
var extendableMessage = message as IProtocolMessageWithExtensions;
if (extendableMessage != null) {
// First add the extensions that are signed by the Provider.
@@ -164,10 +179,10 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
}
}
- return MessageProtections.None;
+ return NoneTask;
}
- return null;
+ return NullTask;
}
#endregion
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/KeyValueFormEncoding.cs b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/KeyValueFormEncoding.cs
index 6ad66c0..9c06e6b 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/KeyValueFormEncoding.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/KeyValueFormEncoding.cs
@@ -11,6 +11,8 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
using System.Globalization;
using System.IO;
using System.Text;
+ using System.Threading;
+ using System.Threading.Tasks;
using DotNetOpenAuth.Messaging;
using Validation;
@@ -131,12 +133,13 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// <param name="data">The stream of Key-Value Form encoded bytes.</param>
/// <returns>The deserialized dictionary.</returns>
/// <exception cref="FormatException">Thrown when the data is not in the expected format.</exception>
- public IDictionary<string, string> GetDictionary(Stream data) {
+ public async Task<IDictionary<string, string>> GetDictionaryAsync(Stream data, CancellationToken cancellationToken) {
using (StreamReader reader = new StreamReader(data, textEncoding)) {
var dict = new Dictionary<string, string>();
int line_num = 0;
string line;
- while ((line = reader.ReadLine()) != null) {
+ while ((line = await reader.ReadLineAsync()) != null) {
+ cancellationToken.ThrowIfCancellationRequested();
line_num++;
if (this.ConformanceLevel == KeyValueFormConformanceLevel.Loose) {
line = line.Trim();
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs
index 5a6b8bb..89bcd77 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs
@@ -7,12 +7,19 @@
namespace DotNetOpenAuth.OpenId.ChannelElements {
using System;
using System.Collections.Generic;
+ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
+ using System.Net.Http;
+ using System.Net.Http.Headers;
using System.Text;
+ using System.Threading;
+ using System.Threading.Tasks;
+
+ using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
using DotNetOpenAuth.OpenId.Extensions;
@@ -40,13 +47,14 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
private KeyValueFormEncoding keyValueForm = new KeyValueFormEncoding();
/// <summary>
- /// Initializes a new instance of the <see cref="OpenIdChannel"/> class.
+ /// Initializes a new instance of the <see cref="OpenIdChannel" /> class.
/// </summary>
/// <param name="messageTypeProvider">A class prepared to analyze incoming messages and indicate what concrete
/// message types can deserialize from it.</param>
/// <param name="bindingElements">The binding elements to use in sending and receiving messages.</param>
- protected OpenIdChannel(IMessageFactory messageTypeProvider, IChannelBindingElement[] bindingElements)
- : base(messageTypeProvider, bindingElements) {
+ /// <param name="hostFactories">The host factories.</param>
+ protected OpenIdChannel(IMessageFactory messageTypeProvider, IChannelBindingElement[] bindingElements, IHostFactories hostFactories)
+ : base(messageTypeProvider, bindingElements, hostFactories ?? new DefaultOpenIdHostFactories()) {
Requires.NotNull(messageTypeProvider, "messageTypeProvider");
// Customize the binding element order, since we play some tricks for higher
@@ -68,33 +76,30 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
}
this.CustomizeBindingElementOrder(outgoingBindingElements, incomingBindingElements);
-
- // Change out the standard web request handler to reflect the standard
- // OpenID pattern that outgoing web requests are to unknown and untrusted
- // servers on the Internet.
- this.WebRequestHandler = new UntrustedWebRequestHandler();
}
/// <summary>
/// Verifies the integrity and applicability of an incoming message.
/// </summary>
/// <param name="message">The message just received.</param>
- /// <exception cref="ProtocolException">
- /// Thrown when the message is somehow invalid, except for check_authentication messages.
- /// This can be due to tampering, replay attack or expiration, among other things.
- /// </exception>
- protected override void ProcessIncomingMessage(IProtocolMessage message) {
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// A task that completes with the asynchronous operation.
+ /// </returns>
+ /// <exception cref="ProtocolException">Thrown when the message is somehow invalid, except for check_authentication messages.
+ /// This can be due to tampering, replay attack or expiration, among other things.</exception>
+ protected override async Task ProcessIncomingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
var checkAuthRequest = message as CheckAuthenticationRequest;
if (checkAuthRequest != null) {
IndirectSignedResponse originalResponse = new IndirectSignedResponse(checkAuthRequest, this);
try {
- base.ProcessIncomingMessage(originalResponse);
+ await base.ProcessIncomingMessageAsync(originalResponse, cancellationToken);
checkAuthRequest.IsValid = true;
} catch (ProtocolException) {
checkAuthRequest.IsValid = false;
}
} else {
- base.ProcessIncomingMessage(message);
+ await base.ProcessIncomingMessageAsync(message, cancellationToken);
}
// Convert an OpenID indirect error message, which we never expect
@@ -120,7 +125,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// <returns>
/// The <see cref="HttpWebRequest"/> prepared to send the request.
/// </returns>
- protected override HttpWebRequest CreateHttpRequest(IDirectedProtocolMessage request) {
+ protected override HttpRequestMessage CreateHttpRequest(IDirectedProtocolMessage request) {
return this.InitializeRequestAsPost(request);
}
@@ -128,13 +133,16 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Gets the protocol message that may be in the given HTTP response.
/// </summary>
/// <param name="response">The response that is anticipated to contain an protocol message.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The deserialized message parts, if found. Null otherwise.
/// </returns>
/// <exception cref="ProtocolException">Thrown when the response is not valid.</exception>
- protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) {
+ protected override async Task<IDictionary<string, string>> ReadFromResponseCoreAsync(HttpResponseMessage response, CancellationToken cancellationToken) {
try {
- return this.keyValueForm.GetDictionary(response.ResponseStream);
+ using (var responseStream = await response.Content.ReadAsStreamAsync()) {
+ return await this.keyValueForm.GetDictionaryAsync(responseStream, cancellationToken);
+ }
} catch (FormatException ex) {
throw ErrorUtilities.Wrap(ex, ex.Message);
}
@@ -145,7 +153,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// </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) {
+ protected override void OnReceivingDirectResponse(HttpResponseMessage response, IDirectResponseProtocolMessage message) {
base.OnReceivingDirectResponse(response, message);
// Verify that the expected HTTP status code was used for the message,
@@ -155,10 +163,10 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
var httpDirectResponse = message as IHttpDirectResponse;
if (httpDirectResponse != null) {
ErrorUtilities.VerifyProtocol(
- httpDirectResponse.HttpStatusCode == response.Status,
+ httpDirectResponse.HttpStatusCode == response.StatusCode,
MessagingStrings.UnexpectedHttpStatusCode,
(int)httpDirectResponse.HttpStatusCode,
- (int)response.Status);
+ (int)response.StatusCode);
}
}
}
@@ -174,55 +182,81 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// <remarks>
/// This method implements spec V1.0 section 5.3.
/// </remarks>
- protected override OutgoingWebResponse PrepareDirectResponse(IProtocolMessage response) {
+ protected override HttpResponseMessage PrepareDirectResponse(IProtocolMessage response) {
var messageAccessor = this.MessageDescriptions.GetAccessor(response);
var fields = messageAccessor.Serialize();
byte[] keyValueEncoding = KeyValueFormEncoding.GetBytes(fields);
- OutgoingWebResponse preparedResponse = new OutgoingWebResponse();
+ var preparedResponse = new HttpResponseMessage();
ApplyMessageTemplate(response, preparedResponse);
- preparedResponse.Headers.Add(HttpResponseHeader.ContentType, KeyValueFormContentType);
- preparedResponse.OriginalMessage = response;
- preparedResponse.ResponseStream = new MemoryStream(keyValueEncoding);
+ var content = new StreamContent(new MemoryStream(keyValueEncoding));
+ content.Headers.ContentType = new MediaTypeHeaderValue(KeyValueFormContentType);
+ preparedResponse.Content = content;
IHttpDirectResponse httpMessage = response as IHttpDirectResponse;
if (httpMessage != null) {
- preparedResponse.Status = httpMessage.HttpStatusCode;
+ preparedResponse.StatusCode = httpMessage.HttpStatusCode;
}
return preparedResponse;
}
/// <summary>
- /// Gets the direct response of a direct HTTP request.
+ /// Provides derived-types the opportunity to wrap an <see cref="HttpMessageHandler" /> with another one.
+ /// </summary>
+ /// <param name="innerHandler">The inner handler received from <see cref="IHostFactories" /></param>
+ /// <returns>
+ /// The handler to use in <see cref="HttpClient" /> instances.
+ /// </returns>
+ protected override HttpMessageHandler WrapMessageHandler(HttpMessageHandler innerHandler) {
+ return new ErrorFilteringMessageHandler(base.WrapMessageHandler(innerHandler));
+ }
+
+ /// <summary>
+ /// An HTTP handler that throws an exception if the response message's HTTP status code doesn't fall
+ /// within those allowed by the OpenID spec.
/// </summary>
- /// <param name="webRequest">The web request.</param>
- /// <returns>The response to the web request.</returns>
- /// <exception cref="ProtocolException">Thrown on network or protocol errors.</exception>
- protected override IncomingWebResponse GetDirectResponse(HttpWebRequest webRequest) {
- IncomingWebResponse response = this.WebRequestHandler.GetResponse(webRequest, DirectWebRequestOptions.AcceptAllHttpResponses);
-
- // Filter the responses to the allowable set of HTTP status codes.
- if (response.Status != HttpStatusCode.OK && response.Status != HttpStatusCode.BadRequest) {
- if (Logger.Channel.IsErrorEnabled) {
- using (var reader = new StreamReader(response.ResponseStream)) {
+ private class ErrorFilteringMessageHandler : DelegatingHandler {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ErrorFilteringMessageHandler" /> class.
+ /// </summary>
+ /// <param name="innerHandler">The inner handler which is responsible for processing the HTTP response messages.</param>
+ internal ErrorFilteringMessageHandler(HttpMessageHandler innerHandler)
+ : base(innerHandler) {
+ }
+
+ /// <summary>
+ /// Sends an HTTP request to the inner handler to send to the server as an asynchronous operation.
+ /// </summary>
+ /// <param name="request">The HTTP request message to send to the server.</param>
+ /// <param name="cancellationToken">A cancellation token to cancel operation.</param>
+ /// <returns>
+ /// Returns <see cref="T:System.Threading.Tasks.Task`1" />. The task object representing the asynchronous operation.
+ /// </returns>
+ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) {
+ var response = await base.SendAsync(request, cancellationToken);
+
+ // Filter the responses to the allowable set of HTTP status codes.
+ if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.BadRequest) {
+ if (Logger.Channel.IsErrorEnabled) {
+ var content = await response.Content.ReadAsStringAsync();
Logger.Channel.ErrorFormat(
"Unexpected HTTP status code {0} {1} received in direct response:{2}{3}",
- (int)response.Status,
- response.Status,
+ (int)response.StatusCode,
+ response.StatusCode,
Environment.NewLine,
- reader.ReadToEnd());
+ content);
}
- }
- // Call dispose before throwing since we're not including the response in the
- // exception we're throwing.
- response.Dispose();
+ // Call dispose before throwing since we're not including the response in the
+ // exception we're throwing.
+ response.Dispose();
- ErrorUtilities.ThrowProtocol(OpenIdStrings.UnexpectedHttpStatusCode, (int)response.Status, response.Status);
- }
+ ErrorUtilities.ThrowProtocol(OpenIdStrings.UnexpectedHttpStatusCode, (int)response.StatusCode, response.StatusCode);
+ }
- return response;
+ return response;
+ }
}
}
}
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ReturnToSignatureBindingElement.cs b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ReturnToSignatureBindingElement.cs
index 726c01f..2aad922 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ReturnToSignatureBindingElement.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ReturnToSignatureBindingElement.cs
@@ -9,6 +9,8 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Security.Cryptography;
+ using System.Threading;
+ using System.Threading.Tasks;
using System.Web;
using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
@@ -32,6 +34,17 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// </remarks>
internal class ReturnToSignatureBindingElement : IChannelBindingElement {
/// <summary>
+ /// A reusable pre-completed task that may be returned multiple times to reduce GC pressure.
+ /// </summary>
+ private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+
+ /// <summary>
+ /// A reusable pre-completed task that may be returned multiple times to reduce GC pressure.
+ /// </summary>
+ private static readonly Task<MessageProtections?> NoneTask =
+ Task.FromResult<MessageProtections?>(MessageProtections.None);
+
+ /// <summary>
/// The name of the callback parameter we'll tack onto the return_to value
/// to store our signature on the return_to parameter.
/// </summary>
@@ -90,6 +103,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Prepares a message for sending based on the rules of this channel binding element.
/// </summary>
/// <param name="message">The message to prepare for sending.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The protections (if any) that this binding element applied to the message.
/// Null if this binding element did not even apply to this binding element.
@@ -98,7 +112,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Implementations that provide message protection must honor the
/// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
/// </remarks>
- public MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) {
+ public Task<MessageProtections?> ProcessOutgoingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
SignedResponseRequest request = message as SignedResponseRequest;
if (request != null && request.ReturnTo != null && request.SignReturnTo) {
var cryptoKeyPair = this.cryptoKeyStore.GetCurrentKey(SecretUri.AbsoluteUri, OpenIdElement.Configuration.MaxAuthenticationTime);
@@ -107,10 +121,10 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
request.AddReturnToArguments(ReturnToSignatureParameterName, signature);
// We return none because we are not signing the entire message (only a part).
- return MessageProtections.None;
+ return NoneTask;
}
- return null;
+ return NullTask;
}
/// <summary>
@@ -118,6 +132,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// validates an incoming message based on the rules of this channel binding element.
/// </summary>
/// <param name="message">The incoming message to process.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The protections (if any) that this binding element applied to the message.
/// Null if this binding element did not even apply to this binding element.
@@ -130,7 +145,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Implementations that provide message protection must honor the
/// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
/// </remarks>
- public MessageProtections? ProcessIncomingMessage(IProtocolMessage message) {
+ public Task<MessageProtections?> ProcessIncomingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
IndirectSignedResponse response = message as IndirectSignedResponse;
if (response != null) {
@@ -150,11 +165,11 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
Logger.Bindings.WarnFormat("The return_to signature failed verification.");
}
- return MessageProtections.None;
+ return NoneTask;
}
}
- return null;
+ return NullTask;
}
#endregion
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SigningBindingElement.cs b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SigningBindingElement.cs
index 584b0e9..8f602cf 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SigningBindingElement.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SigningBindingElement.cs
@@ -11,6 +11,8 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
using System.Globalization;
using System.Linq;
using System.Net.Security;
+ using System.Threading;
+ using System.Threading.Tasks;
using System.Web;
using DotNetOpenAuth.Loggers;
using DotNetOpenAuth.Messaging;
@@ -23,6 +25,11 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Signs and verifies authentication assertions.
/// </summary>
internal abstract class SigningBindingElement : IChannelBindingElement {
+ /// <summary>
+ /// A reusable pre-completed task that may be returned multiple times to reduce GC pressure.
+ /// </summary>
+ private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+
#region IChannelBindingElement Properties
/// <summary>
@@ -53,12 +60,13 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Prepares a message for sending based on the rules of this channel binding element.
/// </summary>
/// <param name="message">The message to prepare for sending.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The protections (if any) that this binding element applied to the message.
/// Null if this binding element did not even apply to this binding element.
/// </returns>
- public virtual MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) {
- return null;
+ public virtual Task<MessageProtections?> ProcessOutgoingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
+ return NullTask;
}
/// <summary>
@@ -66,6 +74,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// validates an incoming message based on the rules of this channel binding element.
/// </summary>
/// <param name="message">The incoming message to process.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The protections (if any) that this binding element applied to the message.
/// Null if this binding element did not even apply to this binding element.
@@ -74,7 +83,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Thrown when the binding element rules indicate that this message is invalid and should
/// NOT be processed.
/// </exception>
- public MessageProtections? ProcessIncomingMessage(IProtocolMessage message) {
+ public async Task<MessageProtections?> ProcessIncomingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
var signedMessage = message as ITamperResistantOpenIdMessage;
if (signedMessage != null) {
Logger.Bindings.DebugFormat("Verifying incoming {0} message signature of: {1}", message.GetType().Name, signedMessage.Signature);
@@ -92,7 +101,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
} else {
ErrorUtilities.VerifyInternal(this.Channel != null, "Cannot verify private association signature because we don't have a channel.");
- protectionsApplied = this.VerifySignatureByUnrecognizedHandle(message, signedMessage, protectionsApplied);
+ protectionsApplied = await this.VerifySignatureByUnrecognizedHandleAsync(message, signedMessage, protectionsApplied, cancellationToken);
}
return protectionsApplied;
@@ -107,8 +116,9 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// <param name="message">The message.</param>
/// <param name="signedMessage">The signed message.</param>
/// <param name="protectionsApplied">The protections applied.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The applied protections.</returns>
- protected abstract MessageProtections VerifySignatureByUnrecognizedHandle(IProtocolMessage message, ITamperResistantOpenIdMessage signedMessage, MessageProtections protectionsApplied);
+ protected abstract Task<MessageProtections> VerifySignatureByUnrecognizedHandleAsync(IProtocolMessage message, ITamperResistantOpenIdMessage signedMessage, MessageProtections protectionsApplied, CancellationToken cancellationToken);
#endregion
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SkipSecurityBindingElement.cs b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SkipSecurityBindingElement.cs
index d162cf6..ad8d59e 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SkipSecurityBindingElement.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SkipSecurityBindingElement.cs
@@ -10,12 +10,19 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
using System.Diagnostics;
using System.Linq;
using System.Text;
+ using System.Threading;
+ using System.Threading.Tasks;
using DotNetOpenAuth.Messaging;
/// <summary>
/// Spoofs security checks on incoming OpenID messages.
/// </summary>
internal class SkipSecurityBindingElement : IChannelBindingElement {
+ /// <summary>
+ /// A reusable pre-completed task that may be returned multiple times to reduce GC pressure.
+ /// </summary>
+ private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+
#region IChannelBindingElement Members
/// <summary>
@@ -42,6 +49,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Prepares a message for sending based on the rules of this channel binding element.
/// </summary>
/// <param name="message">The message to prepare for sending.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The protections (if any) that this binding element applied to the message.
/// Null if this binding element did not even apply to this binding element.
@@ -50,7 +58,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Implementations that provide message protection must honor the
/// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
/// </remarks>
- public MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) {
+ public Task<MessageProtections?> ProcessOutgoingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
Debug.Fail("SkipSecurityBindingElement.ProcessOutgoingMessage should never be called.");
return null;
}
@@ -60,6 +68,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// validates an incoming message based on the rules of this channel binding element.
/// </summary>
/// <param name="message">The incoming message to process.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The protections (if any) that this binding element applied to the message.
/// Null if this binding element did not even apply to this binding element.
@@ -72,14 +81,14 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Implementations that provide message protection must honor the
/// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
/// </remarks>
- public MessageProtections? ProcessIncomingMessage(IProtocolMessage message) {
+ public Task<MessageProtections?> ProcessIncomingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
var signedMessage = message as ITamperResistantOpenIdMessage;
if (signedMessage != null) {
Logger.Bindings.DebugFormat("Skipped security checks of incoming {0} message for preview purposes.", message.GetType().Name);
- return this.Protection;
+ return Task.FromResult<MessageProtections?>(this.Protection);
}
- return null;
+ return NullTask;
}
#endregion