summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OpenId/OpenId
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2012-12-31 22:54:20 -0800
committerAndrew Arnott <andrewarnott@gmail.com>2012-12-31 22:54:20 -0800
commit30cdda15c5e8b6db0d7260697c0a13c06943afec (patch)
tree4b3ea104a96a617502bc11193ad2a99c59d917d7 /src/DotNetOpenAuth.OpenId/OpenId
parent90b6aa8ba9d15e0254eccf05b73b24f334128654 (diff)
downloadDotNetOpenAuth-30cdda15c5e8b6db0d7260697c0a13c06943afec.zip
DotNetOpenAuth-30cdda15c5e8b6db0d7260697c0a13c06943afec.tar.gz
DotNetOpenAuth-30cdda15c5e8b6db0d7260697c0a13c06943afec.tar.bz2
DNOA.OpenId.RP now builds.
Diffstat (limited to 'src/DotNetOpenAuth.OpenId/OpenId')
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/BackwardCompatibilityBindingElement.cs19
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ExtensionsBindingElement.cs19
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs9
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ReturnToSignatureBindingElement.cs19
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SigningBindingElement.cs14
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SkipSecurityBindingElement.cs12
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/IOpenIdHost.cs2
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/Messages/NegativeAssertionResponse.cs40
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/OpenIdUtilities.cs42
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/RelyingParty/IAuthenticationRequest.cs17
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/UntrustedWebRequestHandler.cs44
11 files changed, 158 insertions, 79 deletions
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/BackwardCompatibilityBindingElement.cs b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/BackwardCompatibilityBindingElement.cs
index ff8a766..c448e2f 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;
@@ -16,6 +18,11 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// are required to send back with positive assertions.
/// </summary>
internal class BackwardCompatibilityBindingElement : IChannelBindingElement {
+ private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+
+ 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.
@@ -59,7 +66,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 +76,10 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
request.AddReturnToArguments(ClaimedIdentifierParameterName, authRequest.ClaimedIdentifier);
}
- return MessageProtections.None;
+ return NoneTask;
}
- return null;
+ return NullTask;
}
/// <summary>
@@ -92,7 +99,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 +125,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..2a5946a 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;
@@ -21,6 +23,11 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// their carrying OpenID messages.
/// </summary>
internal class ExtensionsBindingElement : IChannelBindingElement {
+ private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+
+ 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>
@@ -77,7 +84,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 +127,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>
@@ -143,7 +150,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 +171,10 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
}
}
- return MessageProtections.None;
+ return NoneTask;
}
- return null;
+ return NullTask;
}
#endregion
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs
index eb4ca65..221994a 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs
@@ -16,6 +16,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
+ using System.Threading;
using System.Threading.Tasks;
using DotNetOpenAuth.Configuration;
@@ -51,7 +52,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// <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, IHostFactories hostFactories)
+ protected OpenIdChannel(IMessageFactory messageTypeProvider, IChannelBindingElement[] bindingElements, IHostFactories hostFactories = null)
: base(messageTypeProvider, bindingElements, hostFactories ?? new DefaultOpenIdHostFactories()) {
Requires.NotNull(messageTypeProvider, "messageTypeProvider");
@@ -84,18 +85,18 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// 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) {
+ 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
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ReturnToSignatureBindingElement.cs b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ReturnToSignatureBindingElement.cs
index 726c01f..c55704d 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;
@@ -31,6 +33,11 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// anything except a particular message part.</para>
/// </remarks>
internal class ReturnToSignatureBindingElement : IChannelBindingElement {
+ private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+
+ 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.
@@ -98,7 +105,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 +114,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>
@@ -130,7 +137,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 +157,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..83d45a1 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,8 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Signs and verifies authentication assertions.
/// </summary>
internal abstract class SigningBindingElement : IChannelBindingElement {
+ private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+
#region IChannelBindingElement Properties
/// <summary>
@@ -57,8 +61,8 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// 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>
@@ -74,7 +78,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 +96,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;
@@ -108,7 +112,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// <param name="signedMessage">The signed message.</param>
/// <param name="protectionsApplied">The protections applied.</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..900a422 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SkipSecurityBindingElement.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SkipSecurityBindingElement.cs
@@ -10,12 +10,16 @@ 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 {
+ private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+
#region IChannelBindingElement Members
/// <summary>
@@ -50,7 +54,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;
}
@@ -72,14 +76,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
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/IOpenIdHost.cs b/src/DotNetOpenAuth.OpenId/OpenId/IOpenIdHost.cs
index 0c5bf80..cf52fef 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/IOpenIdHost.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/IOpenIdHost.cs
@@ -22,7 +22,7 @@ namespace DotNetOpenAuth.OpenId {
SecuritySettings SecuritySettings { get; }
/// <summary>
- /// Gets the web request handler.
+ /// Gets the factory for various dependencies.
/// </summary>
IHostFactories HostFactories { get; }
}
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/Messages/NegativeAssertionResponse.cs b/src/DotNetOpenAuth.OpenId/OpenId/Messages/NegativeAssertionResponse.cs
index d67e9fe..1bb52b9 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/Messages/NegativeAssertionResponse.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/Messages/NegativeAssertionResponse.cs
@@ -9,6 +9,7 @@ namespace DotNetOpenAuth.OpenId.Messages {
using System.Collections.Generic;
using System.Linq;
using System.Text;
+ using System.Threading;
using System.Threading.Tasks;
using DotNetOpenAuth.Messaging;
using Validation;
@@ -22,9 +23,19 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// <summary>
/// Initializes a new instance of the <see cref="NegativeAssertionResponse"/> class.
/// </summary>
- /// <param name="request">The request that the relying party sent.</param>
- internal NegativeAssertionResponse(CheckIdRequest request)
- : this(request, null) {
+ /// <param name="request">The request.</param>
+ private NegativeAssertionResponse(SignedResponseRequest request)
+ : base(request, GetMode(request)) {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="NegativeAssertionResponse"/> class.
+ /// </summary>
+ /// <param name="version">The version.</param>
+ /// <param name="relyingPartyReturnTo">The relying party return to.</param>
+ /// <param name="mode">The value of the openid.mode parameter.</param>
+ internal NegativeAssertionResponse(Version version, Uri relyingPartyReturnTo, string mode)
+ : base(version, relyingPartyReturnTo, mode) {
}
/// <summary>
@@ -32,24 +43,17 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// </summary>
/// <param name="request">The request that the relying party sent.</param>
/// <param name="channel">The channel to use to simulate construction of the user_setup_url, if applicable. May be null, but the user_setup_url will not be constructed.</param>
- internal NegativeAssertionResponse(SignedResponseRequest request, Channel channel)
- : base(request, GetMode(request)) {
+ internal static async Task<NegativeAssertionResponse> CreateAsync(SignedResponseRequest request, CancellationToken cancellationToken, Channel channel = null) {
+ var result = new NegativeAssertionResponse(request);
+
// If appropriate, and when we're provided with a channel to do it,
// go ahead and construct the user_setup_url
- if (this.Version.Major < 2 && request.Immediate && channel != null) {
+ if (result.Version.Major < 2 && request.Immediate && channel != null) {
// All requests are CheckIdRequests in OpenID 1.x, so this cast should be safe.
- this.UserSetupUrl = ConstructUserSetupUrl((CheckIdRequest)request, channel);
+ result.UserSetupUrl = await ConstructUserSetupUrlAsync((CheckIdRequest)request, channel, cancellationToken);
}
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="NegativeAssertionResponse"/> class.
- /// </summary>
- /// <param name="version">The version.</param>
- /// <param name="relyingPartyReturnTo">The relying party return to.</param>
- /// <param name="mode">The value of the openid.mode parameter.</param>
- internal NegativeAssertionResponse(Version version, Uri relyingPartyReturnTo, string mode)
- : base(version, relyingPartyReturnTo, mode) {
+ return result;
}
/// <summary>
@@ -114,7 +118,7 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// <param name="immediateRequest">The immediate request.</param>
/// <param name="channel">The channel to use to simulate construction of the message.</param>
/// <returns>The value to use for the user_setup_url parameter.</returns>
- private static Uri ConstructUserSetupUrl(CheckIdRequest immediateRequest, Channel channel) {
+ private static async Task<Uri> ConstructUserSetupUrlAsync(CheckIdRequest immediateRequest, Channel channel, CancellationToken cancellationToken) {
Requires.NotNull(immediateRequest, "immediateRequest");
Requires.NotNull(channel, "channel");
ErrorUtilities.VerifyInternal(immediateRequest.Immediate, "Only immediate requests should be sent here.");
@@ -124,7 +128,7 @@ namespace DotNetOpenAuth.OpenId.Messages {
setupRequest.ReturnTo = immediateRequest.ReturnTo;
setupRequest.Realm = immediateRequest.Realm;
setupRequest.AssociationHandle = immediateRequest.AssociationHandle;
- var response = channel.PrepareResponse(setupRequest);
+ var response = await channel.PrepareResponseAsync(setupRequest, cancellationToken);
return response.GetDirectUriRequest();
}
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/OpenIdUtilities.cs b/src/DotNetOpenAuth.OpenId/OpenId/OpenIdUtilities.cs
index f0ed946..f8d542d 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/OpenIdUtilities.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/OpenIdUtilities.cs
@@ -187,24 +187,36 @@ namespace DotNetOpenAuth.OpenId {
internal static HttpClient CreateHttpClient(this IHostFactories hostFactories, bool requireSsl, RequestCachePolicy cachePolicy = null) {
Requires.NotNull(hostFactories, "hostFactories");
- var handler = hostFactories.CreateHttpMessageHandler();
- var webRequestHandler = handler as WebRequestHandler;
- var untrustedHandler = handler as UntrustedWebRequestHandler;
- if (webRequestHandler != null) {
- if (cachePolicy != null) {
- webRequestHandler.CachePolicy = cachePolicy;
- }
- } else if (untrustedHandler != null) {
- if (cachePolicy != null) {
- untrustedHandler.CachePolicy = cachePolicy;
- }
+ var rootHandler = hostFactories.CreateHttpMessageHandler();
+ var handler = rootHandler;
+ do {
+ var webRequestHandler = handler as WebRequestHandler;
+ var untrustedHandler = handler as UntrustedWebRequestHandler;
+ var delegatingHandler = handler as DelegatingHandler;
+ if (webRequestHandler != null) {
+ if (cachePolicy != null) {
+ webRequestHandler.CachePolicy = cachePolicy;
+ }
- untrustedHandler.IsSslRequired = requireSsl;
- } else {
- Logger.Http.DebugFormat("Unable to set cache policy on unsupported {0}.", handler.GetType().FullName);
+ break;
+ } else if (untrustedHandler != null) {
+ if (cachePolicy != null) {
+ untrustedHandler.CachePolicy = cachePolicy;
+ }
+
+ untrustedHandler.IsSslRequired = requireSsl;
+ break;
+ } else if (delegatingHandler != null) {
+ handler = delegatingHandler.InnerHandler;
+ } else {
+ Logger.Http.DebugFormat("Unable to set cache policy on unsupported {0}.", handler.GetType().FullName);
+ break;
+ }
}
+ while (true);
+
- return hostFactories.CreateHttpClient(handler);
+ return hostFactories.CreateHttpClient(rootHandler);
}
internal static Uri GetDirectUriRequest(this HttpResponseMessage response) {
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/RelyingParty/IAuthenticationRequest.cs b/src/DotNetOpenAuth.OpenId/OpenId/RelyingParty/IAuthenticationRequest.cs
index 35a92e1..34a2595 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/RelyingParty/IAuthenticationRequest.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/RelyingParty/IAuthenticationRequest.cs
@@ -10,6 +10,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System.Linq;
using System.Net.Http;
using System.Text;
+ using System.Threading;
+ using System.Threading.Tasks;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Messages;
@@ -25,12 +27,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
AuthenticationRequestMode Mode { get; set; }
/// <summary>
- /// Gets the HTTP response the relying party should send to the user agent
- /// to redirect it to the OpenID Provider to start the OpenID authentication process.
- /// </summary>
- HttpResponseMessage RedirectingResponse { get; }
-
- /// <summary>
/// Gets the URL that the user agent will return to after authentication
/// completes or fails at the Provider.
/// </summary>
@@ -174,12 +170,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
void AddExtension(IOpenIdMessageExtension extension);
/// <summary>
- /// Redirects the user agent to the provider for authentication.
- /// Execution of the current page terminates after this call.
+ /// Gets the HTTP response the relying party should send to the user agent
+ /// to redirect it to the OpenID Provider to start the OpenID authentication process.
/// </summary>
- /// <remarks>
- /// This method requires an ASP.NET HttpContext.
- /// </remarks>
- void RedirectToProvider();
+ Task<HttpResponseMessage> GetRedirectingResponseAsync(CancellationToken cancellationToken);
}
}
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/UntrustedWebRequestHandler.cs b/src/DotNetOpenAuth.OpenId/OpenId/UntrustedWebRequestHandler.cs
index c61ac7f..25d4bb6 100644
--- a/src/DotNetOpenAuth.OpenId/OpenId/UntrustedWebRequestHandler.cs
+++ b/src/DotNetOpenAuth.OpenId/OpenId/UntrustedWebRequestHandler.cs
@@ -207,6 +207,31 @@ namespace DotNetOpenAuth.OpenId {
return client;
}
+ /// <summary>
+ /// Determines whether an exception was thrown because of the remote HTTP server returning HTTP 417 Expectation Failed.
+ /// </summary>
+ /// <param name="ex">The caught exception.</param>
+ /// <returns>
+ /// <c>true</c> if the failure was originally caused by a 417 Exceptation Failed error; otherwise, <c>false</c>.
+ /// </returns>
+ internal static bool IsExceptionFrom417ExpectationFailed(Exception ex) {
+ while (ex != null) {
+ WebException webEx = ex as WebException;
+ if (webEx != null) {
+ HttpWebResponse response = webEx.Response as HttpWebResponse;
+ if (response != null) {
+ if (response.StatusCode == HttpStatusCode.ExpectationFailed) {
+ return true;
+ }
+ }
+ }
+
+ ex = ex.InnerException;
+ }
+
+ return false;
+ }
+
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
this.EnsureAllowableRequestUri(request.RequestUri);
@@ -226,9 +251,24 @@ namespace DotNetOpenAuth.OpenId {
ErrorUtilities.VerifyProtocol(request.Method != HttpMethod.Post, MessagingStrings.UntrustedRedirectsOnPOSTNotSupported);
Uri redirectUri = new Uri(request.RequestUri, response.Headers.Location);
request = request.Clone(redirectUri);
- } else {
- return response;
+ continue;
}
+
+ if (response.StatusCode == HttpStatusCode.ExpectationFailed) {
+ // Some OpenID servers doesn't understand the Expect header and send 417 error back.
+ // If this server just failed from that, alter the ServicePoint for this server
+ // so that we don't send that header again next time (whenever that is).
+ // "Expect: 100-Continue" HTTP header. (see Google Code Issue 72)
+ // We don't want to blindly set all ServicePoints to not use the Expect header
+ // as that would be a security hole allowing any visitor to a web site change
+ // the web site's global behavior when calling that host.
+ // TODO: verify that this still works in DNOA 5.0
+ var servicePoint = ServicePointManager.FindServicePoint(request.RequestUri);
+ Logger.Http.InfoFormat("HTTP POST to {0} resulted in 417 Expectation Failed. Changing ServicePoint to not use Expect: Continue next time.", request.RequestUri);
+ servicePoint.Expect100Continue = false;
+ }
+
+ return response;
}
throw ErrorUtilities.ThrowProtocol(MessagingStrings.TooManyRedirects, originalRequestUri);