diff options
Diffstat (limited to 'src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty')
5 files changed, 111 insertions, 106 deletions
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, |