diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2009-11-05 09:40:27 -0800 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2009-11-05 09:40:27 -0800 |
commit | eea9a4cf1bc749dc10d2469b0814b043694ce86d (patch) | |
tree | 123b77a061fad0d5fc631250b87daff2cb68457f /src | |
parent | 9555817327b24f2a0640c4f1518757fa3032b24b (diff) | |
download | DotNetOpenAuth-eea9a4cf1bc749dc10d2469b0814b043694ce86d.zip DotNetOpenAuth-eea9a4cf1bc749dc10d2469b0814b043694ce86d.tar.gz DotNetOpenAuth-eea9a4cf1bc749dc10d2469b0814b043694ce86d.tar.bz2 |
Added support for RP ASP.NET controls to have an Extensions sub-element that carries extension requests.
Also fixed some random bugs due to code contracts being used in iterator methods.
Diffstat (limited to 'src')
-rw-r--r-- | src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs | 2 | ||||
-rw-r--r-- | src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs | 159 |
2 files changed, 102 insertions, 59 deletions
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs index 65e032c..b753d18 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs @@ -541,7 +541,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// used to determine the user's control of the <see cref="IAuthenticationRequest.ClaimedIdentifier"/>. /// </returns> private IEnumerable<IAuthenticationRequest> CreateRequestsCore(IEnumerable<IAuthenticationRequest> requests) { - Contract.Requires<ArgumentNullException>(requests != null); + ErrorUtilities.VerifyArgumentNotNull(requests, "requests"); // NO CODE CONTRACTS! (yield return used here) // Configure each generated request. int reqIndex = 0; diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs index 5040f74..d7b3229 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs @@ -9,6 +9,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { using System; using System.Collections.Generic; + using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; @@ -25,6 +26,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OpenId.Extensions; using DotNetOpenAuth.OpenId.Extensions.UI; + using DotNetOpenAuth.OpenId.Messages; /// <summary> /// Methods of indicating to the rest of the web site that the user has logged in. @@ -176,6 +178,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { #region Property view state keys /// <summary> + /// The viewstate key to use for storing the value of the <see cref="Extensions"/> property. + /// </summary> + private const string ExtensionsViewStateKey = "Extensions"; + + /// <summary> /// The viewstate key to use for the <see cref="Stateless"/> property. /// </summary> private const string StatelessViewStateKey = "Stateless"; @@ -305,6 +312,22 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { } /// <summary> + /// Gets the collection of extension requests this selector should include in generated requests. + /// </summary> + [PersistenceMode(PersistenceMode.InnerProperty)] + public Collection<IOpenIdMessageExtension> Extensions { + get { + if (this.ViewState[ExtensionsViewStateKey] == null) { + var extensions = new Collection<IOpenIdMessageExtension>(); + this.ViewState[ExtensionsViewStateKey] = extensions; + return extensions; + } else { + return (Collection<IOpenIdMessageExtension>)this.ViewState[ExtensionsViewStateKey]; + } + } + } + + /// <summary> /// Gets or sets a value indicating whether stateless mode is used. /// </summary> [Bindable(true), DefaultValue(StatelessDefault), Category(OpenIdCategory)] @@ -542,65 +565,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// </returns> protected virtual IEnumerable<IAuthenticationRequest> CreateRequests(Identifier identifier) { Contract.Requires<ArgumentNullException>(identifier != null); - IEnumerable<IAuthenticationRequest> requests; - - // Approximate the returnTo (either based on the customize property or the page URL) - // so we can use it to help with Realm resolution. - Uri returnToApproximation = this.ReturnToUrl != null ? new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.ReturnToUrl) : this.Page.Request.Url; - - // Resolve the trust root, and swap out the scheme and port if necessary to match the - // return_to URL, since this match is required by OpenId, and the consumer app - // may be using HTTP at some times and HTTPS at others. - UriBuilder realm = OpenIdUtilities.GetResolvedRealm(this.Page, this.RealmUrl, this.RelyingParty.Channel.GetRequestFromContext()); - realm.Scheme = returnToApproximation.Scheme; - realm.Port = returnToApproximation.Port; - - // Initiate openid request - // We use TryParse here to avoid throwing an exception which - // might slip through our validator control if it is disabled. - Realm typedRealm = new Realm(realm); - if (string.IsNullOrEmpty(this.ReturnToUrl)) { - requests = this.RelyingParty.CreateRequests(identifier, typedRealm); - } else { - // Since the user actually gave us a return_to value, - // the "approximation" is exactly what we want. - requests = this.RelyingParty.CreateRequests(identifier, typedRealm, returnToApproximation); - } - // Some OPs may be listed multiple times (one with HTTPS and the other with HTTP, for example). - // Since we're gathering OPs to try one after the other, just take the first choice of each OP - // and don't try it multiple times. - requests = requests.Distinct(DuplicateRequestedHostsComparer.Instance); - - // Configure each generated request. - foreach (var req in requests) { - if (this.IsPopupAppropriate(req)) { - // Inform ourselves in return_to that we're in a popup. - req.SetUntrustedCallbackArgument(UIPopupCallbackKey, "1"); - - if (req.Provider.IsExtensionSupported<UIRequest>()) { - // Inform the OP that we'll be using a popup window consistent with the UI extension. - req.AddExtension(new UIRequest()); - - // Provide a hint for the client javascript about whether the OP supports the UI extension. - // This is so the window can be made the correct size for the extension. - // If the OP doesn't advertise support for the extension, the javascript will use - // a bigger popup window. - req.SetUntrustedCallbackArgument(PopupUISupportedJSHint, "1"); - } - } - - // Add state that needs to survive across the redirect. - if (!this.Stateless) { - req.SetUntrustedCallbackArgument(UsePersistentCookieCallbackKey, this.UsePersistentCookie.ToString()); - req.SetUntrustedCallbackArgument(ReturnToReceivingControlId, this.ClientID); - } - - ((AuthenticationRequest)req).AssociationPreference = this.AssociationPreference; - if (this.OnLoggingIn(req)) { - yield return req; - } - } + // Delegate to a private method to keep 'yield return' and Code Contract separate. + return this.CreateRequestsCore(identifier); } /// <summary> @@ -896,6 +863,82 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { } /// <summary> + /// Creates the authentication requests for a given user-supplied Identifier. + /// </summary> + /// <param name="identifier">The identifier to create a request for.</param> + /// <returns> + /// A sequence of authentication requests, any one of which may be + /// used to determine the user's control of the <see cref="IAuthenticationRequest.ClaimedIdentifier"/>. + /// </returns> + private IEnumerable<IAuthenticationRequest> CreateRequestsCore(Identifier identifier) { + ErrorUtilities.VerifyArgumentNotNull(identifier, "identifier"); // NO CODE CONTRACTS! (yield return used here) + IEnumerable<IAuthenticationRequest> requests; + + // Approximate the returnTo (either based on the customize property or the page URL) + // so we can use it to help with Realm resolution. + Uri returnToApproximation = this.ReturnToUrl != null ? new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.ReturnToUrl) : this.Page.Request.Url; + + // Resolve the trust root, and swap out the scheme and port if necessary to match the + // return_to URL, since this match is required by OpenId, and the consumer app + // may be using HTTP at some times and HTTPS at others. + UriBuilder realm = OpenIdUtilities.GetResolvedRealm(this.Page, this.RealmUrl, this.RelyingParty.Channel.GetRequestFromContext()); + realm.Scheme = returnToApproximation.Scheme; + realm.Port = returnToApproximation.Port; + + // Initiate openid request + // We use TryParse here to avoid throwing an exception which + // might slip through our validator control if it is disabled. + Realm typedRealm = new Realm(realm); + if (string.IsNullOrEmpty(this.ReturnToUrl)) { + requests = this.RelyingParty.CreateRequests(identifier, typedRealm); + } else { + // Since the user actually gave us a return_to value, + // the "approximation" is exactly what we want. + requests = this.RelyingParty.CreateRequests(identifier, typedRealm, returnToApproximation); + } + + // Some OPs may be listed multiple times (one with HTTPS and the other with HTTP, for example). + // Since we're gathering OPs to try one after the other, just take the first choice of each OP + // and don't try it multiple times. + requests = requests.Distinct(DuplicateRequestedHostsComparer.Instance); + + // Configure each generated request. + foreach (var req in requests) { + if (this.IsPopupAppropriate(req)) { + // Inform ourselves in return_to that we're in a popup. + req.SetUntrustedCallbackArgument(UIPopupCallbackKey, "1"); + + if (req.Provider.IsExtensionSupported<UIRequest>()) { + // Inform the OP that we'll be using a popup window consistent with the UI extension. + req.AddExtension(new UIRequest()); + + // Provide a hint for the client javascript about whether the OP supports the UI extension. + // This is so the window can be made the correct size for the extension. + // If the OP doesn't advertise support for the extension, the javascript will use + // a bigger popup window. + req.SetUntrustedCallbackArgument(PopupUISupportedJSHint, "1"); + } + } + + // Add the extensions injected into the control. + foreach (var extension in this.Extensions) { + req.AddExtension(extension); + } + + // Add state that needs to survive across the redirect. + if (!this.Stateless) { + req.SetUntrustedCallbackArgument(UsePersistentCookieCallbackKey, this.UsePersistentCookie.ToString()); + req.SetUntrustedCallbackArgument(ReturnToReceivingControlId, this.ClientID); + } + + ((AuthenticationRequest)req).AssociationPreference = this.AssociationPreference; + if (this.OnLoggingIn(req)) { + yield return req; + } + } + } + + /// <summary> /// Gets the javascript to executee to redirect or POST an OpenID message to a remote party. /// </summary> /// <param name="request">The authentication request to send.</param> |