summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-11-05 09:40:27 -0800
committerAndrew Arnott <andrewarnott@gmail.com>2009-11-05 09:40:27 -0800
commiteea9a4cf1bc749dc10d2469b0814b043694ce86d (patch)
tree123b77a061fad0d5fc631250b87daff2cb68457f /src
parent9555817327b24f2a0640c4f1518757fa3032b24b (diff)
downloadDotNetOpenAuth-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.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs159
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>