summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OpenId.RelyingParty
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.OpenId.RelyingParty')
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/DotNetOpenAuth.OpenId.RelyingParty.csproj2
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySecurityOptions.cs17
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySigningBindingElement.cs6
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/ReturnToNonceBindingElement.cs19
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/HostMetaDiscoveryService.cs180
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Interop/OpenIdRelyingPartyShim.cs13
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AssociationManager.cs41
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs66
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/Extensions/UIUtilities.cs15
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs78
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/PositiveAuthenticationResponse.cs17
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/packages.config1
12 files changed, 253 insertions, 202 deletions
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/DotNetOpenAuth.OpenId.RelyingParty.csproj b/src/DotNetOpenAuth.OpenId.RelyingParty/DotNetOpenAuth.OpenId.RelyingParty.csproj
index 43fd0ae..5e0eeca 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/DotNetOpenAuth.OpenId.RelyingParty.csproj
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/DotNetOpenAuth.OpenId.RelyingParty.csproj
@@ -79,6 +79,8 @@
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Net.Http.WebRequest" />
<Reference Include="Validation">
<HintPath>..\packages\Validation.2.0.1.12362\lib\portable-windows8+net40+sl5+windowsphone8\Validation.dll</HintPath>
<Private>True</Private>
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySecurityOptions.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySecurityOptions.cs
index b9328dd..01aa16e 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySecurityOptions.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySecurityOptions.cs
@@ -5,6 +5,8 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OpenId.ChannelElements {
+ using System.Threading;
+ using System.Threading.Tasks;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
@@ -13,6 +15,11 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Helps ensure compliance to some properties in the <see cref="RelyingPartySecuritySettings"/>.
/// </summary>
internal class RelyingPartySecurityOptions : IChannelBindingElement {
+ private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+
+ private static readonly Task<MessageProtections?> NoneTask =
+ Task.FromResult<MessageProtections?>(MessageProtections.None);
+
/// <summary>
/// The security settings that are active on the relying party.
/// </summary>
@@ -58,8 +65,8 @@ 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) {
- return null;
+ public Task<MessageProtections?> ProcessOutgoingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
+ return NullTask;
}
/// <summary>
@@ -79,7 +86,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 positiveAssertion = message as PositiveAssertionResponse;
if (positiveAssertion != null) {
ErrorUtilities.VerifyProtocol(
@@ -87,10 +94,10 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
positiveAssertion.LocalIdentifier == positiveAssertion.ClaimedIdentifier,
OpenIdStrings.DelegatingIdentifiersNotAllowed);
- return MessageProtections.None;
+ return NoneTask;
}
- return null;
+ return NullTask;
}
#endregion
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySigningBindingElement.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySigningBindingElement.cs
index 3ec2eee..6a6dee2 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySigningBindingElement.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySigningBindingElement.cs
@@ -9,6 +9,8 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
using System.Collections.Generic;
using System.Linq;
using System.Text;
+ using System.Threading;
+ using System.Threading.Tasks;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
using DotNetOpenAuth.OpenId.Messages;
@@ -78,12 +80,12 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// <returns>
/// The applied protections.
/// </returns>
- protected override MessageProtections VerifySignatureByUnrecognizedHandle(IProtocolMessage message, ITamperResistantOpenIdMessage signedMessage, MessageProtections protectionsApplied) {
+ protected override async Task<MessageProtections> VerifySignatureByUnrecognizedHandleAsync(IProtocolMessage message, ITamperResistantOpenIdMessage signedMessage, MessageProtections protectionsApplied, CancellationToken cancellationToken) {
// We did not recognize the association the provider used to sign the message.
// Ask the provider to check the signature then.
var indirectSignedResponse = (IndirectSignedResponse)signedMessage;
var checkSignatureRequest = new CheckAuthenticationRequest(indirectSignedResponse, this.Channel);
- var checkSignatureResponse = this.Channel.Request<CheckAuthenticationResponse>(checkSignatureRequest);
+ var checkSignatureResponse = await this.Channel.RequestAsync<CheckAuthenticationResponse>(checkSignatureRequest, cancellationToken);
if (!checkSignatureResponse.IsValid) {
Logger.Bindings.Error("Provider reports signature verification failed.");
throw new InvalidSignatureException(message);
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/ReturnToNonceBindingElement.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/ReturnToNonceBindingElement.cs
index c459487..d71a086 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/ReturnToNonceBindingElement.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/ReturnToNonceBindingElement.cs
@@ -9,6 +9,8 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
using System.Collections.Generic;
using System.Linq;
using System.Text;
+ using System.Threading;
+ using System.Threading.Tasks;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
using DotNetOpenAuth.OpenId.Messages;
@@ -46,6 +48,11 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// only on the RP side and only on some messages.</para>
/// </remarks>
internal class ReturnToNonceBindingElement : IChannelBindingElement {
+ private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+
+ private static readonly Task<MessageProtections?> ReplayProtectionTask =
+ Task.FromResult<MessageProtections?>(MessageProtections.ReplayProtection);
+
/// <summary>
/// The context within which return_to nonces must be unique -- they all go into the same bucket.
/// </summary>
@@ -136,17 +143,17 @@ 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) {
// We only add a nonce to some auth requests.
SignedResponseRequest request = message as SignedResponseRequest;
if (this.UseRequestNonce(request)) {
request.AddReturnToArguments(Protocol.ReturnToNonceParameter, CustomNonce.NewNonce().Serialize());
request.SignReturnTo = true; // a nonce without a signature is completely pointless
- return MessageProtections.ReplayProtection;
+ return ReplayProtectionTask;
}
- return null;
+ return NullTask;
}
/// <summary>
@@ -166,7 +173,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 (this.UseRequestNonce(response)) {
if (!response.ReturnToParametersSignatureValidated) {
@@ -190,10 +197,10 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
throw new ReplayedMessageException(message);
}
- return MessageProtections.ReplayProtection;
+ return ReplayProtectionTask;
}
- return null;
+ return NullTask;
}
#endregion
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/HostMetaDiscoveryService.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/HostMetaDiscoveryService.cs
index 1871f19..6a517ad 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/HostMetaDiscoveryService.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/HostMetaDiscoveryService.cs
@@ -13,12 +13,17 @@ namespace DotNetOpenAuth.OpenId {
using System.IO;
using System.Linq;
using System.Net;
+ using System.Net.Cache;
+ using System.Net.Http;
+ using System.Net.Http.Headers;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
+ using System.Threading;
+ using System.Threading.Tasks;
using System.Xml;
using System.Xml.XPath;
using DotNetOpenAuth.Configuration;
@@ -62,10 +67,15 @@ namespace DotNetOpenAuth.OpenId {
/// <summary>
/// Initializes a new instance of the <see cref="HostMetaDiscoveryService"/> class.
/// </summary>
- public HostMetaDiscoveryService() {
+ public HostMetaDiscoveryService(IHostFactories hostFactories) {
+ Requires.NotNull(hostFactories, "hostFactories");
+
this.TrustedHostMetaProxies = new List<HostMetaProxy>();
+ this.HostFactories = hostFactories;
}
+ public IHostFactories HostFactories { get; private set; }
+
/// <summary>
/// Gets the set of URI templates to use to contact host-meta hosting proxies
/// for domain discovery.
@@ -106,27 +116,25 @@ namespace DotNetOpenAuth.OpenId {
/// <returns>
/// A sequence of service endpoints yielded by discovery. Must not be null, but may be empty.
/// </returns>
- public IEnumerable<IdentifierDiscoveryResult> Discover(Identifier identifier, IDirectWebRequestHandler requestHandler, out bool abortDiscoveryChain) {
- abortDiscoveryChain = false;
-
+ public async Task<IdentifierDiscoveryServiceResult> DiscoverAsync(Identifier identifier, CancellationToken cancellationToken) {
// Google Apps are always URIs -- not XRIs.
var uriIdentifier = identifier as UriIdentifier;
if (uriIdentifier == null) {
- return Enumerable.Empty<IdentifierDiscoveryResult>();
+ return new IdentifierDiscoveryServiceResult(Enumerable.Empty<IdentifierDiscoveryResult>());
}
var results = new List<IdentifierDiscoveryResult>();
- string signingHost;
- using (var response = GetXrdsResponse(uriIdentifier, requestHandler, out signingHost)) {
- if (response != null) {
+ using (var response = await this.GetXrdsResponseAsync(uriIdentifier, cancellationToken)) {
+ if (response.Result != null) {
try {
var readerSettings = MessagingUtilities.CreateUntrustedXmlReaderSettings();
- var document = new XrdsDocument(XmlReader.Create(response.ResponseStream, readerSettings));
- ValidateXmlDSig(document, uriIdentifier, response, signingHost);
+ var responseStream = await response.Result.Content.ReadAsStreamAsync();
+ var document = new XrdsDocument(XmlReader.Create(responseStream, readerSettings));
+ await ValidateXmlDSigAsync(document, uriIdentifier, response.Result, response.SigningHost);
var xrds = GetXrdElements(document, uriIdentifier.Uri.Host);
// Look for claimed identifier template URIs for an additional XRDS document.
- results.AddRange(GetExternalServices(xrds, uriIdentifier, requestHandler));
+ results.AddRange(await this.GetExternalServicesAsync(xrds, uriIdentifier, cancellationToken));
// If we couldn't find any claimed identifiers, look for OP identifiers.
// Normally this would be the opposite (OP Identifiers take precedence over
@@ -136,15 +144,13 @@ namespace DotNetOpenAuth.OpenId {
if (results.Count == 0) {
results.AddRange(xrds.CreateServiceEndpoints(uriIdentifier, uriIdentifier));
}
-
- abortDiscoveryChain = true;
} catch (XmlException ex) {
- Logger.Yadis.ErrorFormat("Error while parsing XRDS document at {0} pointed to by host-meta: {1}", response.FinalUri, ex);
+ Logger.Yadis.ErrorFormat("Error while parsing XRDS document at {0} pointed to by host-meta: {1}", response.Result.RequestMessage.RequestUri, ex);
}
}
}
- return results;
+ return new IdentifierDiscoveryServiceResult(results, abortDiscoveryChain: true);
}
#endregion
@@ -181,10 +187,9 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="identifier">The identifier under discovery.</param>
/// <param name="requestHandler">The request handler.</param>
/// <returns>The discovered services.</returns>
- private static IEnumerable<IdentifierDiscoveryResult> GetExternalServices(IEnumerable<XrdElement> xrds, UriIdentifier identifier, IDirectWebRequestHandler requestHandler) {
+ private async Task<IEnumerable<IdentifierDiscoveryResult>> GetExternalServicesAsync(IEnumerable<XrdElement> xrds, UriIdentifier identifier, CancellationToken cancellationToken) {
Requires.NotNull(xrds, "xrds");
Requires.NotNull(identifier, "identifier");
- Requires.NotNull(requestHandler, "requestHandler");
var results = new List<IdentifierDiscoveryResult>();
foreach (var serviceElement in GetDescribedByServices(xrds)) {
@@ -194,10 +199,11 @@ namespace DotNetOpenAuth.OpenId {
Uri externalLocation = new Uri(templateNode.Value.Trim().Replace("{%uri}", Uri.EscapeDataString(identifier.Uri.AbsoluteUri)));
string nextAuthority = nextAuthorityNode != null ? nextAuthorityNode.Value.Trim() : identifier.Uri.Host;
try {
- using (var externalXrdsResponse = GetXrdsResponse(identifier, requestHandler, externalLocation)) {
+ using (var externalXrdsResponse = await this.GetXrdsResponseAsync(identifier, externalLocation, cancellationToken)) {
var readerSettings = MessagingUtilities.CreateUntrustedXmlReaderSettings();
- XrdsDocument externalXrds = new XrdsDocument(XmlReader.Create(externalXrdsResponse.ResponseStream, readerSettings));
- ValidateXmlDSig(externalXrds, identifier, externalXrdsResponse, nextAuthority);
+ var responseStream = await externalXrdsResponse.Content.ReadAsStreamAsync();
+ XrdsDocument externalXrds = new XrdsDocument(XmlReader.Create(responseStream, readerSettings));
+ await ValidateXmlDSigAsync(externalXrds, identifier, externalXrdsResponse, nextAuthority);
results.AddRange(GetXrdElements(externalXrds, identifier).CreateServiceEndpoints(identifier, identifier));
}
} catch (ProtocolException ex) {
@@ -220,7 +226,7 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="signingHost">The host name on the certificate that should be used to verify the signature in the XRDS.</param>
/// <exception cref="ProtocolException">Thrown if the XRDS document has an invalid or a missing signature.</exception>
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "XmlDSig", Justification = "xml")]
- private static void ValidateXmlDSig(XrdsDocument document, UriIdentifier identifier, IncomingWebResponse response, string signingHost) {
+ private static async Task ValidateXmlDSigAsync(XrdsDocument document, UriIdentifier identifier, HttpResponseMessage response, string signingHost) {
Requires.NotNull(document, "document");
Requires.NotNull(identifier, "identifier");
Requires.NotNull(response, "response");
@@ -246,11 +252,12 @@ namespace DotNetOpenAuth.OpenId {
ErrorUtilities.VerifyProtocol(string.Equals(hostName, signingHost, StringComparison.OrdinalIgnoreCase), OpenIdStrings.MisdirectedSigningCertificate, hostName, signingHost);
// Verify the signature itself
- byte[] signature = Convert.FromBase64String(response.Headers["Signature"]);
+ byte[] signature = Convert.FromBase64String(response.Headers.GetValues("Signature").First());
var provider = (RSACryptoServiceProvider)certs.First().PublicKey.Key;
- byte[] data = new byte[response.ResponseStream.Length];
- response.ResponseStream.Seek(0, SeekOrigin.Begin);
- response.ResponseStream.Read(data, 0, data.Length);
+ var responseStream = await response.Content.ReadAsStreamAsync();
+ byte[] data = new byte[responseStream.Length];
+ responseStream.Seek(0, SeekOrigin.Begin);
+ await responseStream.ReadAsync(data, 0, data.Length);
ErrorUtilities.VerifyProtocol(provider.VerifyData(data, "SHA1", signature), OpenIdStrings.InvalidDSig);
}
@@ -292,21 +299,28 @@ namespace DotNetOpenAuth.OpenId {
/// A HTTP response carrying an XRDS document.
/// </returns>
/// <exception cref="ProtocolException">Thrown if the XRDS document could not be obtained.</exception>
- private static IncomingWebResponse GetXrdsResponse(UriIdentifier identifier, IDirectWebRequestHandler requestHandler, Uri xrdsLocation) {
+ private async Task<HttpResponseMessage> GetXrdsResponseAsync(UriIdentifier identifier, Uri xrdsLocation, CancellationToken cancellationToken) {
Requires.NotNull(identifier, "identifier");
- Requires.NotNull(requestHandler, "requestHandler");
Requires.NotNull(xrdsLocation, "xrdsLocation");
- var request = (HttpWebRequest)WebRequest.Create(xrdsLocation);
- request.CachePolicy = Yadis.IdentifierDiscoveryCachePolicy;
- request.Accept = ContentTypes.Xrds;
- var options = identifier.IsDiscoverySecureEndToEnd ? DirectWebRequestOptions.RequireSsl : DirectWebRequestOptions.None;
- var response = requestHandler.GetResponse(request, options).GetSnapshot(Yadis.MaximumResultToScan);
- if (!string.Equals(response.ContentType.MediaType, ContentTypes.Xrds, StringComparison.Ordinal)) {
- Logger.Yadis.WarnFormat("Host-meta pointed to XRDS at {0}, but Content-Type at that URL was unexpected value '{1}'.", xrdsLocation, response.ContentType);
- }
+ using (var httpClient = this.HostFactories.CreateHttpClient(identifier.IsDiscoverySecureEndToEnd, Yadis.IdentifierDiscoveryCachePolicy)) {
+ var request = new HttpRequestMessage(HttpMethod.Get, xrdsLocation);
+ request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(ContentTypes.Xrds));
+ var response = await httpClient.SendAsync(request, cancellationToken);
+ try {
+ if (!string.Equals(response.Content.Headers.ContentType.MediaType, ContentTypes.Xrds, StringComparison.Ordinal)) {
+ Logger.Yadis.WarnFormat(
+ "Host-meta pointed to XRDS at {0}, but Content-Type at that URL was unexpected value '{1}'.",
+ xrdsLocation,
+ response.Content.Headers.ContentType);
+ }
- return response;
+ return response;
+ } catch {
+ response.Dispose();
+ throw;
+ }
+ }
}
/// <summary>
@@ -358,17 +372,16 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="signingHost">The host name on the certificate that should be used to verify the signature in the XRDS.</param>
/// <returns>A HTTP response carrying an XRDS document, or <c>null</c> if one could not be obtained.</returns>
/// <exception cref="ProtocolException">Thrown if the XRDS document could not be obtained.</exception>
- private IncomingWebResponse GetXrdsResponse(UriIdentifier identifier, IDirectWebRequestHandler requestHandler, out string signingHost) {
+ private async Task<ResultWithSigningHost<HttpResponseMessage>> GetXrdsResponseAsync(UriIdentifier identifier, CancellationToken cancellationToken) {
Requires.NotNull(identifier, "identifier");
- Requires.NotNull(requestHandler, "requestHandler");
- Uri xrdsLocation = this.GetXrdsLocation(identifier, requestHandler, out signingHost);
- if (xrdsLocation == null) {
- return null;
- }
- var response = GetXrdsResponse(identifier, requestHandler, xrdsLocation);
+ var result = await this.GetXrdsLocationAsync(identifier, cancellationToken);
+ if (result.Result == null) {
+ return new ResultWithSigningHost<HttpResponseMessage>();
+ }
- return response;
+ var response = await this.GetXrdsResponseAsync(identifier, result.Result, cancellationToken);
+ return new ResultWithSigningHost<HttpResponseMessage>(response, result.SigningHost);
}
/// <summary>
@@ -378,26 +391,26 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="requestHandler">The request handler.</param>
/// <param name="signingHost">The host name on the certificate that should be used to verify the signature in the XRDS.</param>
/// <returns>An absolute URI, or <c>null</c> if one could not be determined.</returns>
- private Uri GetXrdsLocation(UriIdentifier identifier, IDirectWebRequestHandler requestHandler, out string signingHost) {
+ private async Task<ResultWithSigningHost<Uri>> GetXrdsLocationAsync(UriIdentifier identifier, CancellationToken cancellationToken) {
Requires.NotNull(identifier, "identifier");
- Requires.NotNull(requestHandler, "requestHandler");
- using (var hostMetaResponse = this.GetHostMeta(identifier, requestHandler, out signingHost)) {
- if (hostMetaResponse == null) {
- return null;
+
+ using (var hostMetaResponse = await this.GetHostMetaAsync(identifier, cancellationToken)) {
+ if (hostMetaResponse.Result == null) {
+ return new ResultWithSigningHost<Uri>();
}
- using (var sr = hostMetaResponse.GetResponseReader()) {
- string line = sr.ReadLine();
+ using (var sr = new StreamReader(await hostMetaResponse.Result.Content.ReadAsStreamAsync())) {
+ string line = await sr.ReadLineAsync();
Match m = HostMetaLink.Match(line);
if (m.Success) {
Uri location = new Uri(m.Groups["location"].Value);
- Logger.Yadis.InfoFormat("Found link to XRDS at {0} in host-meta document {1}.", location, hostMetaResponse.FinalUri);
- return location;
+ Logger.Yadis.InfoFormat("Found link to XRDS at {0} in host-meta document {1}.", location, hostMetaResponse.Result.RequestMessage.RequestUri);
+ return new ResultWithSigningHost<Uri>(location, hostMetaResponse.SigningHost);
}
}
- Logger.Yadis.WarnFormat("Could not find link to XRDS in host-meta document: {0}", hostMetaResponse.FinalUri);
- return null;
+ Logger.Yadis.WarnFormat("Could not find link to XRDS in host-meta document: {0}", hostMetaResponse.Result.RequestMessage.RequestUri);
+ return new ResultWithSigningHost<Uri>();
}
}
@@ -410,35 +423,29 @@ namespace DotNetOpenAuth.OpenId {
/// <returns>
/// The host-meta response, or <c>null</c> if no host-meta document could be obtained.
/// </returns>
- private IncomingWebResponse GetHostMeta(UriIdentifier identifier, IDirectWebRequestHandler requestHandler, out string signingHost) {
+ private async Task<ResultWithSigningHost<HttpResponseMessage>> GetHostMetaAsync(UriIdentifier identifier, CancellationToken cancellationToken) {
Requires.NotNull(identifier, "identifier");
- Requires.NotNull(requestHandler, "requestHandler");
- foreach (var hostMetaProxy in this.GetHostMetaLocations(identifier)) {
- var hostMetaLocation = hostMetaProxy.GetProxy(identifier);
- var request = (HttpWebRequest)WebRequest.Create(hostMetaLocation);
- request.CachePolicy = Yadis.IdentifierDiscoveryCachePolicy;
- var options = DirectWebRequestOptions.AcceptAllHttpResponses;
- if (identifier.IsDiscoverySecureEndToEnd) {
- options |= DirectWebRequestOptions.RequireSsl;
- }
- var response = requestHandler.GetResponse(request, options).GetSnapshot(Yadis.MaximumResultToScan);
- try {
- if (response.Status == HttpStatusCode.OK) {
- Logger.Yadis.InfoFormat("Found host-meta for {0} at: {1}", identifier.Uri.Host, hostMetaLocation);
- signingHost = hostMetaProxy.GetSigningHost(identifier);
- return response;
- } else {
- Logger.Yadis.InfoFormat("Could not obtain host-meta for {0} from {1}", identifier.Uri.Host, hostMetaLocation);
+
+ using (var httpClient = this.HostFactories.CreateHttpClient(identifier.IsDiscoverySecureEndToEnd, Yadis.IdentifierDiscoveryCachePolicy)) {
+ foreach (var hostMetaProxy in this.GetHostMetaLocations(identifier)) {
+ var hostMetaLocation = hostMetaProxy.GetProxy(identifier);
+ var response = await httpClient.GetAsync(hostMetaLocation, cancellationToken);
+ try {
+ if (response.IsSuccessStatusCode) {
+ Logger.Yadis.InfoFormat("Found host-meta for {0} at: {1}", identifier.Uri.Host, hostMetaLocation);
+ return new ResultWithSigningHost<HttpResponseMessage>(response, hostMetaProxy.GetSigningHost(identifier));
+ } else {
+ Logger.Yadis.InfoFormat("Could not obtain host-meta for {0} from {1}", identifier.Uri.Host, hostMetaLocation);
+ response.Dispose();
+ }
+ } catch {
response.Dispose();
+ throw;
}
- } catch {
- response.Dispose();
- throw;
}
}
- signingHost = null;
- return null;
+ return new ResultWithSigningHost<HttpResponseMessage>();
}
/// <summary>
@@ -546,5 +553,22 @@ namespace DotNetOpenAuth.OpenId {
return this.ProxyFormat.GetHashCode();
}
}
+
+ private struct ResultWithSigningHost<T> : IDisposable {
+ internal ResultWithSigningHost(T result, string signingHost)
+ : this() {
+ this.Result = result;
+ this.SigningHost = signingHost;
+ }
+
+ public T Result { get; private set; }
+
+ public string SigningHost { get; private set; }
+
+ public void Dispose() {
+ var disposable = this.Result as IDisposable;
+ disposable.DisposeIfNotNull();
+ }
+ }
}
}
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Interop/OpenIdRelyingPartyShim.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Interop/OpenIdRelyingPartyShim.cs
index eb37d86..9568c1d 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Interop/OpenIdRelyingPartyShim.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Interop/OpenIdRelyingPartyShim.cs
@@ -11,6 +11,7 @@ namespace DotNetOpenAuth.OpenId.Interop {
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
+ using System.Threading;
using System.Web;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
@@ -68,8 +69,9 @@ namespace DotNetOpenAuth.OpenId.Interop {
/// <exception cref="ProtocolException">Thrown if no OpenID endpoint could be found.</exception>
[SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "COM requires primitive types")]
public string CreateRequest(string userSuppliedIdentifier, string realm, string returnToUrl) {
- var request = relyingParty.CreateRequest(userSuppliedIdentifier, realm, new Uri(returnToUrl));
- return request.RedirectingResponse.GetDirectUriRequest(relyingParty.Channel).AbsoluteUri;
+ var request = relyingParty.CreateRequestAsync(userSuppliedIdentifier, realm, new Uri(returnToUrl)).Result;
+ var response = request.GetRedirectingResponseAsync(CancellationToken.None).Result;
+ return response.GetDirectUriRequest().AbsoluteUri;
}
/// <summary>
@@ -91,7 +93,7 @@ namespace DotNetOpenAuth.OpenId.Interop {
/// <exception cref="ProtocolException">Thrown if no OpenID endpoint could be found.</exception>
[SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "COM requires primitive types")]
public string CreateRequestWithSimpleRegistration(string userSuppliedIdentifier, string realm, string returnToUrl, string optionalSreg, string requiredSreg) {
- var request = relyingParty.CreateRequest(userSuppliedIdentifier, realm, new Uri(returnToUrl));
+ var request = relyingParty.CreateRequestAsync(userSuppliedIdentifier, realm, new Uri(returnToUrl)).Result;
ClaimsRequest sreg = new ClaimsRequest();
if (!string.IsNullOrEmpty(optionalSreg)) {
@@ -101,7 +103,8 @@ namespace DotNetOpenAuth.OpenId.Interop {
sreg.SetProfileRequestFromList(requiredSreg.Split(','), DemandLevel.Require);
}
request.AddExtension(sreg);
- return request.RedirectingResponse.GetDirectUriRequest(relyingParty.Channel).AbsoluteUri;
+ var response = request.GetRedirectingResponseAsync(CancellationToken.None).Result;
+ return response.GetDirectUriRequest().AbsoluteUri;
}
/// <summary>
@@ -120,7 +123,7 @@ namespace DotNetOpenAuth.OpenId.Interop {
}
HttpRequestBase requestInfo = new HttpRequestInfo(method, new Uri(url), form: formMap);
- var response = relyingParty.GetResponse(requestInfo);
+ var response = relyingParty.GetResponseAsync(requestInfo, CancellationToken.None).Result;
if (response != null) {
return new AuthenticationResponseShim(response);
}
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AssociationManager.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AssociationManager.cs
index dfb307b..14566e1 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AssociationManager.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AssociationManager.cs
@@ -11,6 +11,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System.Net;
using System.Security;
using System.Text;
+ using System.Threading;
+ using System.Threading.Tasks;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.ChannelElements;
using DotNetOpenAuth.OpenId.Messages;
@@ -131,8 +133,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="provider">The provider to get an association for.</param>
/// <returns>The existing or new association; <c>null</c> if none existed and one could not be created.</returns>
- internal Association GetOrCreateAssociation(IProviderEndpoint provider) {
- return this.GetExistingAssociation(provider) ?? this.CreateNewAssociation(provider);
+ internal async Task<Association> GetOrCreateAssociationAsync(IProviderEndpoint provider, CancellationToken cancellationToken) {
+ return this.GetExistingAssociation(provider) ?? await this.CreateNewAssociationAsync(provider, cancellationToken);
}
/// <summary>
@@ -148,7 +150,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// association store.
/// Any new association is automatically added to the <see cref="associationStore"/>.
/// </remarks>
- private Association CreateNewAssociation(IProviderEndpoint provider) {
+ private async Task<Association> CreateNewAssociationAsync(IProviderEndpoint provider, CancellationToken cancellationToken) {
Requires.NotNull(provider, "provider");
// If there is no association store, there is no point in creating an association.
@@ -160,7 +162,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
var associateRequest = AssociateRequestRelyingParty.Create(this.securitySettings, provider);
const int RenegotiateRetries = 1;
- return this.CreateNewAssociation(provider, associateRequest, RenegotiateRetries);
+ return await this.CreateNewAssociationAsync(provider, associateRequest, RenegotiateRetries, cancellationToken);
} catch (VerificationException ex) {
// See Trac ticket #163. In partial trust host environments, the
// Diffie-Hellman implementation we're using for HTTP OP endpoints
@@ -182,7 +184,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// The newly created association, or null if no association can be created with
/// the given Provider given the current security settings.
/// </returns>
- private Association CreateNewAssociation(IProviderEndpoint provider, AssociateRequest associateRequest, int retriesRemaining) {
+ private async Task<Association> CreateNewAssociationAsync(IProviderEndpoint provider, AssociateRequest associateRequest, int retriesRemaining, CancellationToken cancellationToken) {
Requires.NotNull(provider, "provider");
if (associateRequest == null || retriesRemaining < 0) {
@@ -191,8 +193,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
return null;
}
+ Exception exception = null;
try {
- var associateResponse = this.channel.Request(associateRequest);
+ var associateResponse = await this.channel.RequestAsync(associateRequest, cancellationToken);
var associateSuccessfulResponse = associateResponse as IAssociateSuccessfulResponseRelyingParty;
var associateUnsuccessfulResponse = associateResponse as AssociateUnsuccessfulResponse;
if (associateSuccessfulResponse != null) {
@@ -224,23 +227,27 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
associateUnsuccessfulResponse.SessionType);
associateRequest = AssociateRequestRelyingParty.Create(this.securitySettings, provider, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType);
- return this.CreateNewAssociation(provider, associateRequest, retriesRemaining - 1);
+ return await this.CreateNewAssociationAsync(provider, associateRequest, retriesRemaining - 1, cancellationToken);
} else {
throw new ProtocolException(MessagingStrings.UnexpectedMessageReceivedOfMany);
}
} catch (ProtocolException ex) {
- // If the association failed because the remote server can't handle Expect: 100 Continue headers,
- // then our web request handler should have already accomodated for future calls. Go ahead and
- // immediately make one of those future calls now to try to get the association to succeed.
- if (StandardWebRequestHandler.IsExceptionFrom417ExpectationFailed(ex)) {
- return this.CreateNewAssociation(provider, associateRequest, retriesRemaining - 1);
- }
+ exception = ex;
+ }
- // Since having associations with OPs is not totally critical, we'll log and eat
- // the exception so that auth may continue in dumb mode.
- Logger.OpenId.ErrorFormat("An error occurred while trying to create an association with {0}. {1}", provider.Uri, ex);
- return null;
+ Assumes.NotNull(exception);
+
+ // If the association failed because the remote server can't handle Expect: 100 Continue headers,
+ // then our web request handler should have already accomodated for future calls. Go ahead and
+ // immediately make one of those future calls now to try to get the association to succeed.
+ if (UntrustedWebRequestHandler.IsExceptionFrom417ExpectationFailed(exception)) {
+ return await this.CreateNewAssociationAsync(provider, associateRequest, retriesRemaining - 1, cancellationToken);
}
+
+ // Since having associations with OPs is not totally critical, we'll log and eat
+ // the exception so that auth may continue in dumb mode.
+ Logger.OpenId.ErrorFormat("An error occurred while trying to create an association with {0}. {1}", provider.Uri, exception);
+ return null;
}
}
}
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs
index 92af297..f9abc37 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs
@@ -9,10 +9,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
+ using System.Net.Http;
+ using System.ServiceModel.Channels;
using System.Text;
using System.Threading;
+ using System.Threading.Tasks;
using System.Web;
-
using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.ChannelElements;
@@ -95,14 +97,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// to redirect it to the OpenID Provider to start the OpenID authentication process.
/// </summary>
/// <value></value>
- public OutgoingWebResponse RedirectingResponse {
- get {
- foreach (var behavior in this.RelyingParty.Behaviors) {
- behavior.OnOutgoingAuthenticationRequest(this);
- }
-
- return this.RelyingParty.Channel.PrepareResponse(this.CreateRequestMessage());
+ public async Task<HttpResponseMessage> GetRedirectingResponseAsync(CancellationToken cancellationToken) {
+ foreach (var behavior in this.RelyingParty.Behaviors) {
+ behavior.OnOutgoingAuthenticationRequest(this);
}
+
+ var request = await this.CreateRequestMessageAsync(cancellationToken);
+ return await this.RelyingParty.Channel.PrepareResponseAsync(request, cancellationToken);
}
/// <summary>
@@ -293,16 +294,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.extensions.Add(extension);
}
- /// <summary>
- /// Redirects the user agent to the provider for authentication.
- /// </summary>
- /// <remarks>
- /// This method requires an ASP.NET HttpContext.
- /// </remarks>
- public void RedirectToProvider() {
- this.RedirectingResponse.Send();
- }
-
#endregion
/// <summary>
@@ -318,7 +309,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// A sequence of authentication requests, any of which constitutes a valid identity assertion on the Claimed Identifier.
/// Never null, but may be empty.
/// </returns>
- internal static IEnumerable<AuthenticationRequest> Create(Identifier userSuppliedIdentifier, OpenIdRelyingParty relyingParty, Realm realm, Uri returnToUrl, bool createNewAssociationsAsNeeded) {
+ internal static async Task<IEnumerable<AuthenticationRequest>> CreateAsync(Identifier userSuppliedIdentifier, OpenIdRelyingParty relyingParty, Realm realm, Uri returnToUrl, bool createNewAssociationsAsNeeded, CancellationToken cancellationToken) {
Requires.NotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
Requires.NotNull(relyingParty, "relyingParty");
Requires.NotNull(realm, "realm");
@@ -360,7 +351,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// Perform discovery right now (not deferred).
IEnumerable<IdentifierDiscoveryResult> serviceEndpoints;
try {
- var results = relyingParty.Discover(userSuppliedIdentifier).CacheGeneratedResults();
+ var results = (await relyingParty.DiscoverAsync(userSuppliedIdentifier, cancellationToken)).CacheGeneratedResults();
// If any OP Identifier service elements were found, we must not proceed
// to use any Claimed Identifier services, per OpenID 2.0 sections 7.3.2.2 and 11.2.
@@ -381,7 +372,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
serviceEndpoints = relyingParty.SecuritySettings.FilterEndpoints(serviceEndpoints);
// Call another method that defers request generation.
- return CreateInternal(userSuppliedIdentifier, relyingParty, realm, returnToUrl, serviceEndpoints, createNewAssociationsAsNeeded);
+ return await CreateInternalAsync(userSuppliedIdentifier, relyingParty, realm, returnToUrl, serviceEndpoints, createNewAssociationsAsNeeded, cancellationToken);
}
/// <summary>
@@ -401,9 +392,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// based on the properties in this instance.
/// </summary>
/// <returns>The message to send to the Provider.</returns>
- internal SignedResponseRequest CreateRequestMessageTestHook()
- {
- return this.CreateRequestMessage();
+ internal Task<SignedResponseRequest> CreateRequestMessageTestHookAsync(CancellationToken cancellationToken) {
+ return this.CreateRequestMessageAsync(cancellationToken);
}
/// <summary>
@@ -423,18 +413,18 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// All data validation and cleansing steps must have ALREADY taken place
/// before calling this method.
/// </remarks>
- private static IEnumerable<AuthenticationRequest> CreateInternal(Identifier userSuppliedIdentifier, OpenIdRelyingParty relyingParty, Realm realm, Uri returnToUrl, IEnumerable<IdentifierDiscoveryResult> serviceEndpoints, bool createNewAssociationsAsNeeded) {
- // DO NOT USE CODE CONTRACTS IN THIS METHOD, since it uses yield return
- ErrorUtilities.VerifyArgumentNotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
- ErrorUtilities.VerifyArgumentNotNull(relyingParty, "relyingParty");
- ErrorUtilities.VerifyArgumentNotNull(realm, "realm");
- ErrorUtilities.VerifyArgumentNotNull(serviceEndpoints, "serviceEndpoints");
+ private static async Task<IEnumerable<AuthenticationRequest>> CreateInternalAsync(Identifier userSuppliedIdentifier, OpenIdRelyingParty relyingParty, Realm realm, Uri returnToUrl, IEnumerable<IdentifierDiscoveryResult> serviceEndpoints, bool createNewAssociationsAsNeeded, CancellationToken cancellationToken) {
+ Requires.NotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
+ Requires.NotNull(relyingParty, "relyingParty");
+ Requires.NotNull(realm, "realm");
+ Requires.NotNull(serviceEndpoints, "serviceEndpoints");
////
// If shared associations are required, then we had better have an association store.
ErrorUtilities.VerifyOperation(!relyingParty.SecuritySettings.RequireAssociation || relyingParty.AssociationManager.HasAssociationStore, OpenIdStrings.AssociationStoreRequired);
Logger.Yadis.InfoFormat("Performing discovery on user-supplied identifier: {0}", userSuppliedIdentifier);
IEnumerable<IdentifierDiscoveryResult> endpoints = FilterAndSortEndpoints(serviceEndpoints, relyingParty);
+ var results = new List<AuthenticationRequest>();
// Maintain a list of endpoints that we could not form an association with.
// We'll fallback to generating requests to these if the ones we CAN create
@@ -450,7 +440,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// In some scenarios (like the AJAX control wanting ALL auth requests possible),
// we don't want to create associations with every Provider. But we'll use
// associations where they are already formed from previous authentications.
- association = createNewAssociationsAsNeeded ? relyingParty.AssociationManager.GetOrCreateAssociation(endpoint) : relyingParty.AssociationManager.GetExistingAssociation(endpoint);
+ association = createNewAssociationsAsNeeded ? await relyingParty.AssociationManager.GetOrCreateAssociationAsync(endpoint, cancellationToken) : relyingParty.AssociationManager.GetExistingAssociation(endpoint);
if (association == null && createNewAssociationsAsNeeded) {
Logger.OpenId.WarnFormat("Failed to create association with {0}. Skipping to next endpoint.", endpoint.ProviderEndpoint);
@@ -461,7 +451,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
}
- yield return new AuthenticationRequest(endpoint, realm, returnToUrl, relyingParty);
+ results.Add(new AuthenticationRequest(endpoint, realm, returnToUrl, relyingParty));
}
// Now that we've run out of endpoints that respond to association requests,
@@ -481,10 +471,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// because we've already tried. Let's not have it waste time trying again.
var authRequest = new AuthenticationRequest(endpoint, realm, returnToUrl, relyingParty);
authRequest.associationPreference = AssociationPreference.IfAlreadyEstablished;
- yield return authRequest;
+ results.Add(authRequest);
}
}
}
+
+ return results;
}
/// <summary>
@@ -535,8 +527,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// based on the properties in this instance.
/// </summary>
/// <returns>The message to send to the Provider.</returns>
- private SignedResponseRequest CreateRequestMessage() {
- Association association = this.GetAssociation();
+ private async Task<SignedResponseRequest> CreateRequestMessageAsync(CancellationToken cancellationToken) {
+ Association association = await this.GetAssociationAsync(cancellationToken);
SignedResponseRequest request;
if (!this.IsExtensionOnly) {
@@ -566,11 +558,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Gets the association to use for this authentication request.
/// </summary>
/// <returns>The association to use; <c>null</c> to use 'dumb mode'.</returns>
- private Association GetAssociation() {
+ private async Task<Association> GetAssociationAsync(CancellationToken cancellationToken) {
Association association = null;
switch (this.associationPreference) {
case AssociationPreference.IfPossible:
- association = this.RelyingParty.AssociationManager.GetOrCreateAssociation(this.DiscoveryResult);
+ association = await this.RelyingParty.AssociationManager.GetOrCreateAssociationAsync(this.DiscoveryResult, cancellationToken);
if (association == null) {
// Avoid trying to create the association again if the redirecting response
// is generated again.
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/Extensions/UIUtilities.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/Extensions/UIUtilities.cs
index a5de08b..80bfe65 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/Extensions/UIUtilities.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/Extensions/UIUtilities.cs
@@ -6,10 +6,12 @@
namespace DotNetOpenAuth.OpenId.RelyingParty.Extensions.UI {
using System;
- using System.Globalization;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OpenId.RelyingParty;
- using Validation;
+using System.Globalization;
+using System.Threading;
+using System.Threading.Tasks;
+using DotNetOpenAuth.Messaging;
+using DotNetOpenAuth.OpenId.RelyingParty;
+using Validation;
/// <summary>
/// Constants used in implementing support for the UI extension.
@@ -23,12 +25,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty.Extensions.UI {
/// <param name="request">The authentication request to place in the window.</param>
/// <param name="windowName">The name to assign to the popup window.</param>
/// <returns>A string starting with 'window.open' and forming just that one method call.</returns>
- internal static string GetWindowPopupScript(OpenIdRelyingParty relyingParty, IAuthenticationRequest request, string windowName) {
+ internal static async Task<string> GetWindowPopupScriptAsync(OpenIdRelyingParty relyingParty, IAuthenticationRequest request, string windowName, CancellationToken cancellationToken) {
Requires.NotNull(relyingParty, "relyingParty");
Requires.NotNull(request, "request");
Requires.NotNullOrEmpty(windowName, "windowName");
- Uri popupUrl = request.RedirectingResponse.GetDirectUriRequest(relyingParty.Channel);
+ var response = await request.GetRedirectingResponseAsync(cancellationToken);
+ Uri popupUrl = response.GetDirectUriRequest();
return string.Format(
CultureInfo.InvariantCulture,
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs
index 2177591..a55e042 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs
@@ -14,8 +14,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System.Globalization;
using System.Linq;
using System.Net;
+ using System.Net.Http;
+ using System.Net.Http.Headers;
using System.Net.Mime;
using System.Text;
+ using System.Threading;
+ using System.Threading.Tasks;
using System.Web;
using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
@@ -272,11 +276,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
- /// Gets the web request handler to use for discovery and the part of
- /// authentication where direct messages are sent to an untrusted remote party.
+ /// Gets the factory for various dependencies.
/// </summary>
- IDirectWebRequestHandler IOpenIdHost.WebRequestHandler {
- get { return this.Channel.WebRequestHandler; }
+ IHostFactories IOpenIdHost.HostFactories {
+ get { return this.channel.HostFactories; }
}
/// <summary>
@@ -288,14 +291,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
- /// Gets the web request handler to use for discovery and the part of
- /// authentication where direct messages are sent to an untrusted remote party.
- /// </summary>
- internal IDirectWebRequestHandler WebRequestHandler {
- get { return this.Channel.WebRequestHandler; }
- }
-
- /// <summary>
/// Gets the association manager.
/// </summary>
internal AssociationManager AssociationManager { get; private set; }
@@ -339,12 +334,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// an object to send to the user agent to initiate the authentication.
/// </returns>
/// <exception cref="ProtocolException">Thrown if no OpenID endpoint could be found.</exception>
- public IAuthenticationRequest CreateRequest(Identifier userSuppliedIdentifier, Realm realm, Uri returnToUrl) {
+ public async Task<IAuthenticationRequest> CreateRequestAsync(Identifier userSuppliedIdentifier, Realm realm, Uri returnToUrl, CancellationToken cancellationToken = default(CancellationToken)) {
Requires.NotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
Requires.NotNull(realm, "realm");
Requires.NotNull(returnToUrl, "returnToUrl");
try {
- return this.CreateRequests(userSuppliedIdentifier, realm, returnToUrl).First();
+ return (await this.CreateRequestsAsync(userSuppliedIdentifier, realm, returnToUrl)).First();
} catch (InvalidOperationException ex) {
throw ErrorUtilities.Wrap(ex, OpenIdStrings.OpenIdEndpointNotFound);
}
@@ -371,11 +366,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </remarks>
/// <exception cref="ProtocolException">Thrown if no OpenID endpoint could be found.</exception>
/// <exception cref="InvalidOperationException">Thrown if <see cref="HttpContext.Current">HttpContext.Current</see> == <c>null</c>.</exception>
- public IAuthenticationRequest CreateRequest(Identifier userSuppliedIdentifier, Realm realm) {
+ public async Task<IAuthenticationRequest> CreateRequestAsync(Identifier userSuppliedIdentifier, Realm realm) {
Requires.NotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
Requires.NotNull(realm, "realm");
try {
- var result = this.CreateRequests(userSuppliedIdentifier, realm).First();
+ var result = (await this.CreateRequestsAsync(userSuppliedIdentifier, realm)).First();
Assumes.True(result != null);
return result;
} catch (InvalidOperationException ex) {
@@ -399,10 +394,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </remarks>
/// <exception cref="ProtocolException">Thrown if no OpenID endpoint could be found.</exception>
/// <exception cref="InvalidOperationException">Thrown if <see cref="HttpContext.Current">HttpContext.Current</see> == <c>null</c>.</exception>
- public IAuthenticationRequest CreateRequest(Identifier userSuppliedIdentifier) {
+ public async Task<IAuthenticationRequest> CreateRequestAsync(Identifier userSuppliedIdentifier) {
Requires.NotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
try {
- return this.CreateRequests(userSuppliedIdentifier).First();
+ return (await this.CreateRequestsAsync(userSuppliedIdentifier)).First();
} catch (InvalidOperationException ex) {
throw ErrorUtilities.Wrap(ex, OpenIdStrings.OpenIdEndpointNotFound);
}
@@ -435,12 +430,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <para>No exception is thrown if no OpenID endpoints were discovered.
/// An empty enumerable is returned instead.</para>
/// </remarks>
- public virtual IEnumerable<IAuthenticationRequest> CreateRequests(Identifier userSuppliedIdentifier, Realm realm, Uri returnToUrl) {
+ public virtual async Task<IEnumerable<IAuthenticationRequest>> CreateRequestsAsync(Identifier userSuppliedIdentifier, Realm realm, Uri returnToUrl, CancellationToken cancellationToken = default(CancellationToken)) {
Requires.NotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
Requires.NotNull(realm, "realm");
Requires.NotNull(returnToUrl, "returnToUrl");
- return AuthenticationRequest.Create(userSuppliedIdentifier, this, realm, returnToUrl, true).Cast<IAuthenticationRequest>().CacheGeneratedResults();
+ var requests = await AuthenticationRequest.CreateAsync(userSuppliedIdentifier, this, realm, returnToUrl, true, cancellationToken);
+ return requests.Cast<IAuthenticationRequest>().CacheGeneratedResults();
}
/// <summary>
@@ -468,7 +464,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <para>Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.</para>
/// </remarks>
/// <exception cref="InvalidOperationException">Thrown if <see cref="HttpContext.Current">HttpContext.Current</see> == <c>null</c>.</exception>
- public IEnumerable<IAuthenticationRequest> CreateRequests(Identifier userSuppliedIdentifier, Realm realm) {
+ public async Task<IEnumerable<IAuthenticationRequest>> CreateRequestsAsync(Identifier userSuppliedIdentifier, Realm realm) {
RequiresEx.ValidState(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired);
Requires.NotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
Requires.NotNull(realm, "realm");
@@ -491,7 +487,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
returnTo.AppendQueryArgs(returnToParams);
- return this.CreateRequests(userSuppliedIdentifier, realm, returnTo.Uri);
+ return await this.CreateRequestsAsync(userSuppliedIdentifier, realm, returnTo.Uri);
}
/// <summary>
@@ -514,11 +510,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <para>Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.</para>
/// </remarks>
/// <exception cref="InvalidOperationException">Thrown if <see cref="HttpContext.Current">HttpContext.Current</see> == <c>null</c>.</exception>
- public IEnumerable<IAuthenticationRequest> CreateRequests(Identifier userSuppliedIdentifier) {
+ public async Task<IEnumerable<IAuthenticationRequest>> CreateRequestsAsync(Identifier userSuppliedIdentifier) {
Requires.NotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
RequiresEx.ValidState(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired);
- return this.CreateRequests(userSuppliedIdentifier, Realm.AutoDetect);
+ return await this.CreateRequestsAsync(userSuppliedIdentifier, Realm.AutoDetect);
}
/// <summary>
@@ -528,9 +524,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <remarks>
/// <para>Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.</para>
/// </remarks>
- public IAuthenticationResponse GetResponse() {
+ public Task<IAuthenticationResponse> GetResponseAsync(CancellationToken cancellationToken) {
RequiresEx.ValidState(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired);
- return this.GetResponse(this.Channel.GetRequestFromContext());
+ return this.GetResponseAsync(this.Channel.GetRequestFromContext(), cancellationToken);
}
/// <summary>
@@ -538,10 +534,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="httpRequestInfo">The HTTP request that may be carrying an authentication response from the Provider.</param>
/// <returns>The processed authentication response if there is any; <c>null</c> otherwise.</returns>
- public IAuthenticationResponse GetResponse(HttpRequestBase httpRequestInfo) {
+ public async Task<IAuthenticationResponse> GetResponseAsync(HttpRequestBase httpRequestInfo, CancellationToken cancellationToken) {
Requires.NotNull(httpRequestInfo, "httpRequestInfo");
try {
- var message = this.Channel.ReadFromRequest(httpRequestInfo);
+ var message = await this.Channel.ReadFromRequestAsync(httpRequestInfo, cancellationToken);
PositiveAssertionResponse positiveAssertion;
NegativeAssertionResponse negativeAssertion;
IndirectSignedResponse positiveExtensionOnly;
@@ -554,7 +550,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
OpenIdStrings.PositiveAssertionFromNonQualifiedProvider,
providerEndpoint.Uri);
- var response = new PositiveAuthenticationResponse(positiveAssertion, this);
+ var response = await PositiveAuthenticationResponse.CreateAsync(positiveAssertion, this, cancellationToken);
foreach (var behavior in this.Behaviors) {
behavior.OnIncomingPositiveAssertion(response);
}
@@ -581,10 +577,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <remarks>
/// <para>Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.</para>
/// </remarks>
- public OutgoingWebResponse ProcessResponseFromPopup() {
+ public Task<HttpResponseMessage> ProcessResponseFromPopupAsync(CancellationToken cancellationToken) {
RequiresEx.ValidState(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired);
- return this.ProcessResponseFromPopup(this.Channel.GetRequestFromContext());
+ return this.ProcessResponseFromPopupAsync(this.Channel.GetRequestFromContext(), cancellationToken);
}
/// <summary>
@@ -592,10 +588,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="request">The incoming HTTP request that is expected to carry an OpenID authentication response.</param>
/// <returns>The HTTP response to send to this HTTP request.</returns>
- public OutgoingWebResponse ProcessResponseFromPopup(HttpRequestBase request) {
+ public Task<HttpResponseMessage> ProcessResponseFromPopupAsync(HttpRequestBase request, CancellationToken cancellationToken) {
Requires.NotNull(request, "request");
- return this.ProcessResponseFromPopup(request, null);
+ return this.ProcessResponseFromPopupAsync(request, null, cancellationToken);
}
/// <summary>
@@ -678,11 +674,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// The HTTP response to send to this HTTP request.
/// </returns>
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "OpenID", Justification = "real word"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "iframe", Justification = "Code contracts")]
- internal OutgoingWebResponse ProcessResponseFromPopup(HttpRequestBase request, Action<AuthenticationStatus> callback) {
+ internal async Task<HttpResponseMessage> ProcessResponseFromPopupAsync(HttpRequestBase request, Action<AuthenticationStatus> callback, CancellationToken cancellationToken) {
Requires.NotNull(request, "request");
string extensionsJson = null;
- var authResponse = this.NonVerifyingRelyingParty.GetResponse();
+ var authResponse = await this.NonVerifyingRelyingParty.GetResponseAsync(cancellationToken);
ErrorUtilities.VerifyProtocol(authResponse != null, OpenIdStrings.PopupRedirectMissingResponse);
// Give the caller a chance to notify the hosting page and fill up the clientScriptExtensions collection.
@@ -734,8 +730,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="identifier">The identifier to discover services for.</param>
/// <returns>A non-null sequence of services discovered for the identifier.</returns>
- internal IEnumerable<IdentifierDiscoveryResult> Discover(Identifier identifier) {
- return this.discoveryServices.Discover(identifier);
+ internal Task<IEnumerable<IdentifierDiscoveryResult>> DiscoverAsync(Identifier identifier, CancellationToken cancellationToken) {
+ return this.discoveryServices.DiscoverAsync(identifier, cancellationToken);
}
/// <summary>
@@ -795,7 +791,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <param name="methodCall">The method to call on the parent window, including
/// parameters. (i.e. "callback('arg1', 2)"). No escaping is done by this method.</param>
/// <returns>The entire HTTP response to send to the popup window or iframe to perform the invocation.</returns>
- private static OutgoingWebResponse InvokeParentPageScript(string methodCall) {
+ private static HttpResponseMessage InvokeParentPageScript(string methodCall) {
Requires.NotNullOrEmpty(methodCall, "methodCall");
Logger.OpenId.DebugFormat("Sending Javascript callback: {0}", methodCall);
@@ -824,9 +820,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
builder.AppendLine("//]]>--></script>");
builder.AppendLine("</body></html>");
- var response = new OutgoingWebResponse();
- response.Body = builder.ToString();
- response.Headers.Add(HttpResponseHeader.ContentType, new ContentType("text/html").ToString());
+ var response = new HttpResponseMessage();
+ response.Content = new StringContent(builder.ToString());
+ response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
return response;
}
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/PositiveAuthenticationResponse.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
index 509eb60..f05abaa 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
@@ -8,6 +8,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System;
using System.Diagnostics;
using System.Linq;
+ using System.Threading;
+ using System.Threading.Tasks;
using System.Web;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Messages;
@@ -24,7 +26,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="response">The positive assertion response that was just received by the Relying Party.</param>
/// <param name="relyingParty">The relying party.</param>
- internal PositiveAuthenticationResponse(PositiveAssertionResponse response, OpenIdRelyingParty relyingParty)
+ private PositiveAuthenticationResponse(PositiveAssertionResponse response, OpenIdRelyingParty relyingParty)
: base(response) {
Requires.NotNull(relyingParty, "relyingParty");
@@ -36,8 +38,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
null,
null);
- this.VerifyDiscoveryMatchesAssertion(relyingParty);
-
Logger.OpenId.InfoFormat("Received identity assertion for {0} via {1}.", this.Response.ClaimedIdentifier, this.Provider.Uri);
}
@@ -123,6 +123,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
get { return (PositiveAssertionResponse)base.Response; }
}
+ internal static async Task<PositiveAuthenticationResponse> CreateAsync(
+ PositiveAssertionResponse response, OpenIdRelyingParty relyingParty, CancellationToken cancellationToken) {
+ var result = new PositiveAuthenticationResponse(response, relyingParty);
+ await result.VerifyDiscoveryMatchesAssertionAsync(relyingParty, cancellationToken);
+ return result;
+ }
+
/// <summary>
/// Verifies that the positive assertion data matches the results of
/// discovery on the Claimed Identifier.
@@ -134,7 +141,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// This would be an indication of either a misconfigured Provider or
/// an attempt by someone to spoof another user's identity with a rogue Provider.
/// </exception>
- private void VerifyDiscoveryMatchesAssertion(OpenIdRelyingParty relyingParty) {
+ private async Task VerifyDiscoveryMatchesAssertionAsync(OpenIdRelyingParty relyingParty, CancellationToken cancellationToken) {
Logger.OpenId.Debug("Verifying assertion matches identifier discovery results...");
// Ensure that we abide by the RP's rules regarding RequireSsl for this discovery step.
@@ -163,7 +170,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// is signed by the RP before it's considered reliable. In 1.x stateless mode, this RP
// doesn't (and can't) sign its own return_to URL, so its cached discovery information
// is merely a hint that must be verified by performing discovery again here.
- var discoveryResults = relyingParty.Discover(claimedId);
+ var discoveryResults = await relyingParty.DiscoverAsync(claimedId, cancellationToken);
ErrorUtilities.VerifyProtocol(
discoveryResults.Contains(this.Endpoint),
OpenIdStrings.IssuedAssertionFailsIdentifierDiscovery,
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/packages.config b/src/DotNetOpenAuth.OpenId.RelyingParty/packages.config
index 58890d8..1d93cf5 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/packages.config
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/packages.config
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
+ <package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net45" />
<package id="Validation" version="2.0.1.12362" targetFramework="net45" />
</packages> \ No newline at end of file