summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj2
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/UI/UIUtilities.cs52
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs78
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/PopupBehavior.cs31
4 files changed, 162 insertions, 1 deletions
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index 9197cee..02e093a 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -353,6 +353,7 @@
<Compile Include="OpenId\Extensions\SimpleRegistration\Constants.cs" />
<Compile Include="OpenId\Extensions\SimpleRegistration\DemandLevel.cs" />
<Compile Include="OpenId\Extensions\SimpleRegistration\Gender.cs" />
+ <Compile Include="OpenId\Extensions\UI\UIUtilities.cs" />
<Compile Include="OpenId\Extensions\UI\UIModes.cs" />
<Compile Include="OpenId\Extensions\UI\UIRequest.cs" />
<Compile Include="OpenId\Identifier.cs" />
@@ -428,6 +429,7 @@
<Compile Include="OpenId\RelyingParty\OpenIdLogin.cs" />
<Compile Include="OpenId\RelyingParty\OpenIdMobileTextBox.cs" />
<Compile Include="OpenId\RelyingParty\OpenIdTextBox.cs" />
+ <Compile Include="OpenId\RelyingParty\PopupBehavior.cs" />
<Compile Include="OpenId\RelyingParty\PositiveAnonymousResponse.cs" />
<Compile Include="OpenId\RelyingParty\PositiveAuthenticationResponse.cs" />
<Compile Include="OpenId\RelyingParty\AuthenticationStatus.cs" />
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/UI/UIUtilities.cs b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIUtilities.cs
new file mode 100644
index 0000000..ff6ec7f
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIUtilities.cs
@@ -0,0 +1,52 @@
+//-----------------------------------------------------------------------
+// <copyright file="UIUtilities.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.Extensions.UI {
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+
+ /// <summary>
+ /// Constants used in implementing support for the UI extension.
+ /// </summary>
+ public static class UIUtilities {
+ /// <summary>
+ /// The required width of the popup window the relying party creates for the provider.
+ /// </summary>
+ public const int PopupWidth = 450;
+
+ /// <summary>
+ /// The required height of the popup window the relying party creates for the provider.
+ /// </summary>
+ public const int PopupHeight = 500;
+
+ /// <summary>
+ /// Gets the <c>window.open</c> javascript snippet to use to open a popup window
+ /// compliant with the UI extension.
+ /// </summary>
+ /// <param name="relyingParty">The relying party.</param>
+ /// <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) {
+ Contract.Requires(relyingParty != null);
+ Contract.Requires(request != null);
+ Contract.Requires(!string.IsNullOrEmpty(windowName));
+
+ Uri popupUrl = request.RedirectingResponse.GetDirectUriRequest(relyingParty.Channel);
+
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "window.open({0}, {1}, 'status=0,toolbar=0,location=1,resizable=1,scrollbars=1,width={2},height={3}');",
+ MessagingUtilities.GetSafeJavascriptValue(popupUrl.AbsoluteUri),
+ MessagingUtilities.GetSafeJavascriptValue(windowName),
+ PopupWidth,
+ PopupHeight);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs
index 831c53c..adaecc6 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs
@@ -15,9 +15,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
using System.Drawing.Design;
using System.Globalization;
using System.Net;
+ using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Security;
@@ -26,6 +28,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
+ using DotNetOpenAuth.OpenId.Extensions.UI;
/// <summary>
/// An ASP.NET control that provides a minimal text box that is OpenID-aware.
@@ -76,6 +79,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#region Property viewstate keys
/// <summary>
+ /// The viewstate key to use for the <see cref="Popup"/> property.
+ /// </summary>
+ private const string PopupViewStateKey = "Popup";
+
+ /// <summary>
/// The viewstate key to use for the <see cref="RequestEmail"/> property.
/// </summary>
private const string RequestEmailViewStateKey = "RequestEmail";
@@ -170,6 +178,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#region Property defaults
/// <summary>
+ /// The default value for the <see cref="Popup"/> property.
+ /// </summary>
+ private const PopupBehavior PopupDefault = PopupBehavior.Never;
+
+ /// <summary>
/// The default value for the <see cref="Columns"/> property.
/// </summary>
private const int ColumnsDefault = 40;
@@ -277,6 +290,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#endregion
/// <summary>
+ /// The callback parameter to use for recognizing when the callback is in a popup window.
+ /// </summary>
+ private const string UIPopupCallbackKey = "dnoa.uipopup";
+
+ /// <summary>
/// The callback parameter for use with persisting the <see cref="UsePersistentCookie"/> property.
/// </summary>
private const string UsePersistentCookieCallbackKey = "OpenIdTextBox_UsePersistentCookie";
@@ -330,6 +348,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
public event EventHandler<OpenIdEventArgs> SetupRequired;
#endregion
+
#region IEditableTextControl Members
/// <summary>
@@ -428,6 +447,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Gets or sets a value indicating when to use a popup window to complete the login experience.
+ /// </summary>
+ /// <value>The default value is <see cref="PopupBehavior.Never"/>.</value>
+ [Bindable(true), DefaultValue(PopupDefault), Category(BehaviorCategory)]
+ [Description("When to use a popup window to complete the login experience.")]
+ public PopupBehavior Popup {
+ get { return (PopupBehavior)(ViewState[PopupViewStateKey] ?? PopupDefault); }
+ set { ViewState[PopupViewStateKey] = value; }
+ }
+
+ /// <summary>
/// Gets or sets a value indicating whether stateless mode is used.
/// </summary>
[Bindable(true), DefaultValue(StatelessDefault), Category(BehaviorCategory)]
@@ -906,6 +936,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.AddProfileArgs(this.Request);
}
+ if (this.IsPopupAppropriate()) {
+ // Inform the OP that it will appear in a popup window.
+ this.Request.AddExtension(new UIRequest());
+ }
+
// Add state that needs to survive across the redirect.
if (!this.Stateless) {
this.Request.AddCallbackArguments(UsePersistentCookieCallbackKey, this.UsePersistentCookie.ToString(CultureInfo.InvariantCulture));
@@ -931,7 +966,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
if (this.Request != null) {
- this.Request.RedirectToProvider();
+ if (this.IsPopupAppropriate()) {
+ this.ScriptPopupWindow();
+ } else {
+ this.Request.RedirectToProvider();
+ }
}
}
@@ -982,6 +1021,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
var response = this.RelyingParty.GetResponse();
if (response != null) {
+ if (response.GetCallbackArgument(UIPopupCallbackKey) == "1") {
+ // We're in a popup window. We need to close it and pass the
+ // message back to the parent window for processing.
+ this.Page.ClientScript.RegisterStartupScript(this.GetType(), "loginPopupClose", "window.close()", true);
+
+ // TODO: we still need to script sending the message back to the parent window!
+ return;
+ }
+
string persistentString = response.GetCallbackArgument(UsePersistentCookieCallbackKey);
bool persistentBool;
if (persistentString != null && bool.TryParse(persistentString, out persistentBool)) {
@@ -1157,5 +1205,33 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
return rp;
}
+
+ /// <summary>
+ /// Detects whether a popup window should be used to show the Provider's UI
+ /// and applies the UI extension to the request when appropriate.
+ /// </summary>
+ /// <returns><c>true</c> if a popup should be used; <c>false</c> otherwise.</returns>
+ private bool IsPopupAppropriate() {
+ Contract.Requires(this.Request != null);
+
+ return this.Popup == PopupBehavior.Always || this.Request.Provider.IsExtensionSupported<UIRequest>();
+ }
+
+ /// <summary>
+ /// Wires the return page to immediately display a popup window with the Provider in it.
+ /// </summary>
+ private void ScriptPopupWindow() {
+ Contract.Requires(this.Request != null);
+ Contract.Requires(this.RelyingParty != null);
+
+ this.Request.AddCallbackArguments(UIPopupCallbackKey, "1");
+
+ StringBuilder startupScript = new StringBuilder();
+ startupScript.AppendFormat(
+ @"var openidPopup = {0}",
+ UIUtilities.GetWindowPopupScript(this.RelyingParty, this.Request, "openidPopup"));
+
+ this.Page.ClientScript.RegisterStartupScript(this.GetType(), "loginPopup", startupScript.ToString(), true);
+ }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/PopupBehavior.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/PopupBehavior.cs
new file mode 100644
index 0000000..e84f4f5
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/PopupBehavior.cs
@@ -0,0 +1,31 @@
+//-----------------------------------------------------------------------
+// <copyright file="PopupBehavior.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.RelyingParty {
+ /// <summary>
+ /// Several ways that the relying party can direct the user to the Provider
+ /// to complete authentication.
+ /// </summary>
+ public enum PopupBehavior {
+ /// <summary>
+ /// A full browser window redirect will be used to send the
+ /// user to the Provider.
+ /// </summary>
+ Never,
+
+ /// <summary>
+ /// A popup window will be used to send the user to the Provider.
+ /// </summary>
+ Always,
+
+ /// <summary>
+ /// A popup window will be used to send the user to the Provider
+ /// if the Provider advertises support for the popup UI extension;
+ /// otherwise a standard redirect is used.
+ /// </summary>
+ IfProviderSupported,
+ }
+}