diff options
Diffstat (limited to 'src/DotNetOpenAuth.OpenId.RelyingParty')
31 files changed, 2 insertions, 8725 deletions
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/DotNetOpenAuth.OpenId.RelyingParty.csproj b/src/DotNetOpenAuth.OpenId.RelyingParty/DotNetOpenAuth.OpenId.RelyingParty.csproj index c9158ba..4222497 100644 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/DotNetOpenAuth.OpenId.RelyingParty.csproj +++ b/src/DotNetOpenAuth.OpenId.RelyingParty/DotNetOpenAuth.OpenId.RelyingParty.csproj @@ -39,8 +39,6 @@ <Compile Include="OpenId\Messages\AssociateSuccessfulResponseContract.cs" /> <Compile Include="OpenId\Messages\AssociateSuccessfulResponseRelyingParty.cs" /> <Compile Include="OpenId\Messages\AssociateUnencryptedResponseRelyingParty.cs" /> - <Compile Include="OpenId\Mvc\OpenIdAjaxOptions.cs" /> - <Compile Include="OpenId\Mvc\OpenIdHelper.cs" /> <Compile Include="OpenId\RelyingParty\CryptoKeyStoreAsRelyingPartyAssociationStore.cs" /> <Compile Include="OpenId\RelyingParty\IRelyingPartyAssociationStore.cs" /> <Compile Include="OpenId\RelyingParty\Associations.cs" /> @@ -49,47 +47,18 @@ <Compile Include="OpenId\RelyingParty\AuthenticationRequest.cs" /> <Compile Include="OpenId\RelyingParty\DuplicateRequestedHostsComparer.cs" /> <Compile Include="OpenId\RelyingParty\NegativeAuthenticationResponse.cs" /> - <Compile Include="OpenId\RelyingParty\OpenIdAjaxRelyingParty.cs" /> - <Compile Include="OpenId\RelyingParty\OpenIdAjaxTextBox.cs" /> - <Compile Include="OpenId\RelyingParty\OpenIdButton.cs" /> - <Compile Include="OpenId\RelyingParty\OpenIdEventArgs.cs" /> - <Compile Include="OpenId\RelyingParty\OpenIdLogin.cs" /> - <Compile Include="OpenId\RelyingParty\OpenIdMobileTextBox.cs" /> - <Compile Include="OpenId\RelyingParty\OpenIdRelyingPartyAjaxControlBase.cs" /> - <Compile Include="OpenId\RelyingParty\OpenIdRelyingPartyControlBase.cs" /> - <Compile Include="OpenId\RelyingParty\OpenIdSelector.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\FailedAuthenticationResponse.cs" /> <Compile Include="OpenId\RelyingParty\ISetupRequiredAuthenticationResponse.cs" /> <Compile Include="OpenId\RelyingParty\OpenIdRelyingParty.cs" /> <Compile Include="OpenId\RelyingParty\PositiveAuthenticationResponseSnapshot.cs" /> - <Compile Include="OpenId\RelyingParty\SelectorButton.cs" /> - <Compile Include="OpenId\RelyingParty\SelectorButtonContract.cs" /> - <Compile Include="OpenId\RelyingParty\SelectorOpenIdButton.cs" /> - <Compile Include="OpenId\RelyingParty\SelectorProviderButton.cs" /> <Compile Include="OpenId\RelyingParty\SimpleXrdsProviderEndpoint.cs" /> <Compile Include="OpenId\RelyingParty\StandardRelyingPartyApplicationStore.cs" /> <Compile Include="OpenId\RelyingParty\WellKnownProviders.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> <ItemGroup> - <Content Include="OpenId\RelyingParty\login_failure.png" /> - <Content Include="OpenId\RelyingParty\login_success %28lock%29.png" /> - <Content Include="OpenId\RelyingParty\login_success.png" /> - <Content Include="OpenId\RelyingParty\OpenIdAjaxTextBox.css" /> - <Content Include="OpenId\RelyingParty\OpenIdAjaxTextBox.js" /> - <Content Include="OpenId\RelyingParty\OpenIdRelyingPartyAjaxControlBase.js" /> - <Content Include="OpenId\RelyingParty\OpenIdRelyingPartyControlBase.js" /> - <Content Include="OpenId\RelyingParty\OpenIdSelector.css" /> - <Content Include="OpenId\RelyingParty\OpenIdSelector.js" /> - <Content Include="OpenId\RelyingParty\openid_login.png" /> - <Content Include="OpenId\RelyingParty\spinner.gif" /> - </ItemGroup> - <ItemGroup> - <None Include="OpenId\RelyingParty\Controls.cd" /> <None Include="OpenId\RelyingParty\OpenIdRelyingParty.cd" /> </ItemGroup> <ItemGroup> diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Mvc/OpenIdAjaxOptions.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Mvc/OpenIdAjaxOptions.cs deleted file mode 100644 index 4b88d04..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Mvc/OpenIdAjaxOptions.cs +++ /dev/null @@ -1,76 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdAjaxOptions.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.Mvc { - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using System.Text; - using DotNetOpenAuth.Messaging; - - /// <summary> - /// A set of customizations available for the scripts sent to the browser in AJAX OpenID scenarios. - /// </summary> - public class OpenIdAjaxOptions { - /// <summary> - /// Initializes a new instance of the <see cref="OpenIdAjaxOptions"/> class. - /// </summary> - public OpenIdAjaxOptions() { - this.AssertionHiddenFieldId = "openid_openidAuthData"; - this.ReturnUrlHiddenFieldId = "ReturnUrl"; - } - - /// <summary> - /// Gets or sets the ID of the hidden field that should carry the positive assertion - /// until it is posted to the RP. - /// </summary> - public string AssertionHiddenFieldId { get; set; } - - /// <summary> - /// Gets or sets the ID of the hidden field that should be set with the parent window/frame's URL - /// prior to posting the form with the positive assertion. Useful for jQuery popup dialogs. - /// </summary> - public string ReturnUrlHiddenFieldId { get; set; } - - /// <summary> - /// Gets or sets the index of the form in the document.forms array on the browser that should - /// be submitted when the user is ready to send the positive assertion to the RP. - /// </summary> - public int FormIndex { get; set; } - - /// <summary> - /// Gets or sets the id of the form in the document.forms array on the browser that should - /// be submitted when the user is ready to send the positive assertion to the RP. A value - /// in this property takes precedence over any value in the <see cref="FormIndex"/> property. - /// </summary> - /// <value>The form id.</value> - public string FormId { get; set; } - - /// <summary> - /// Gets or sets the preloaded discovery results. - /// </summary> - public string PreloadedDiscoveryResults { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether to print diagnostic trace messages in the browser. - /// </summary> - public bool ShowDiagnosticTrace { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether to show all the "hidden" iframes that facilitate - /// asynchronous authentication of the user for diagnostic purposes. - /// </summary> - public bool ShowDiagnosticIFrame { get; set; } - - /// <summary> - /// Gets the form key to use when accessing the relevant form. - /// </summary> - internal string FormKey { - get { return string.IsNullOrEmpty(this.FormId) ? this.FormIndex.ToString(CultureInfo.InvariantCulture) : MessagingUtilities.GetSafeJavascriptValue(this.FormId); } - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Mvc/OpenIdHelper.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Mvc/OpenIdHelper.cs deleted file mode 100644 index b98e0d6..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Mvc/OpenIdHelper.cs +++ /dev/null @@ -1,431 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdHelper.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.Mvc { - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Diagnostics.Contracts; - using System.Globalization; - using System.IO; - using System.Linq; - using System.Text; - using System.Web; - using System.Web.Mvc; - using System.Web.Routing; - using System.Web.UI; - using DotNetOpenAuth.Configuration; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OpenId; - using DotNetOpenAuth.OpenId.RelyingParty; - - /// <summary> - /// Methods that generate HTML or Javascript for hosting AJAX OpenID "controls" on - /// ASP.NET MVC web sites. - /// </summary> - public static class OpenIdHelper { - /// <summary> - /// Emits a series of stylesheet import tags to support the AJAX OpenID Selector. - /// </summary> - /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param> - /// <returns>HTML that should be sent directly to the browser.</returns> - public static string OpenIdSelectorStyles(this HtmlHelper html) { - Contract.Requires<ArgumentNullException>(html != null); - Contract.Ensures(Contract.Result<string>() != null); - - using (var result = new StringWriter(CultureInfo.CurrentCulture)) { - result.WriteStylesheetLink(OpenId.RelyingParty.OpenIdSelector.EmbeddedStylesheetResourceName); - result.WriteStylesheetLink(OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedStylesheetResourceName); - return result.ToString(); - } - } - - /// <summary> - /// Emits a series of script import tags and some inline script to support the AJAX OpenID Selector. - /// </summary> - /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param> - /// <returns>HTML that should be sent directly to the browser.</returns> - public static string OpenIdSelectorScripts(this HtmlHelper html) { - return OpenIdSelectorScripts(html, null, null); - } - - /// <summary> - /// Emits a series of script import tags and some inline script to support the AJAX OpenID Selector. - /// </summary> - /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param> - /// <param name="selectorOptions">An optional instance of an <see cref="OpenIdSelector"/> control, whose properties have been customized to express how this MVC control should be rendered.</param> - /// <param name="additionalOptions">An optional set of additional script customizations.</param> - /// <returns> - /// HTML that should be sent directly to the browser. - /// </returns> - [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "False positive")] - public static string OpenIdSelectorScripts(this HtmlHelper html, OpenIdSelector selectorOptions, OpenIdAjaxOptions additionalOptions) { - Contract.Requires<ArgumentNullException>(html != null); - Contract.Ensures(Contract.Result<string>() != null); - - bool selectorOptionsOwned = false; - if (selectorOptions == null) { - selectorOptionsOwned = true; - selectorOptions = new OpenId.RelyingParty.OpenIdSelector(); - } - try { - if (additionalOptions == null) { - additionalOptions = new OpenIdAjaxOptions(); - } - - using (StringWriter result = new StringWriter(CultureInfo.CurrentCulture)) { - if (additionalOptions.ShowDiagnosticIFrame || additionalOptions.ShowDiagnosticTrace) { - string scriptFormat = @"window.openid_visible_iframe = {0}; // causes the hidden iframe to show up -window.openid_trace = {1}; // causes lots of messages"; - result.WriteScriptBlock(string.Format( - CultureInfo.InvariantCulture, - scriptFormat, - additionalOptions.ShowDiagnosticIFrame ? "true" : "false", - additionalOptions.ShowDiagnosticTrace ? "true" : "false")); - } - var scriptResources = new[] { - OpenIdRelyingPartyControlBase.EmbeddedJavascriptResource, - OpenIdRelyingPartyAjaxControlBase.EmbeddedAjaxJavascriptResource, - OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedScriptResourceName, - }; - result.WriteScriptTags(scriptResources); - - if (selectorOptions.DownloadYahooUILibrary) { - result.WriteScriptTagsUrls(new[] { "https://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/yuiloader/yuiloader-min.js" }); - } - - using (var blockBuilder = new StringWriter(CultureInfo.CurrentCulture)) { - if (selectorOptions.DownloadYahooUILibrary) { - blockBuilder.WriteLine(@" try { - if (YAHOO) { - var loader = new YAHOO.util.YUILoader({ - require: ['button', 'menu'], - loadOptional: false, - combine: true - }); - - loader.insert(); - } - } catch (e) { }"); - } - - blockBuilder.WriteLine("window.aspnetapppath = '{0}';", VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath)); - - // Positive assertions can last no longer than this library is willing to consider them valid, - // and when they come with OP private associations they last no longer than the OP is willing - // to consider them valid. We assume the OP will hold them valid for at least five minutes. - double assertionLifetimeInMilliseconds = Math.Min(TimeSpan.FromMinutes(5).TotalMilliseconds, Math.Min(OpenIdElement.Configuration.MaxAuthenticationTime.TotalMilliseconds, DotNetOpenAuthSection.Messaging.MaximumMessageLifetime.TotalMilliseconds)); - blockBuilder.WriteLine( - "{0} = {1};", - OpenIdRelyingPartyAjaxControlBase.MaxPositiveAssertionLifetimeJsName, - assertionLifetimeInMilliseconds.ToString(CultureInfo.InvariantCulture)); - - if (additionalOptions.PreloadedDiscoveryResults != null) { - blockBuilder.WriteLine(additionalOptions.PreloadedDiscoveryResults); - } - - string discoverUrl = VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath) + html.RouteCollection["OpenIdDiscover"].GetVirtualPath(html.ViewContext.RequestContext, new RouteValueDictionary(new { identifier = "xxx" })).VirtualPath; - string blockFormat = @" {0} = function (argument, resultFunction, errorCallback) {{ - jQuery.ajax({{ - async: true, - dataType: 'text', - error: function (request, status, error) {{ errorCallback(status, argument); }}, - success: function (result) {{ resultFunction(result, argument); }}, - url: '{1}'.replace('xxx', encodeURIComponent(argument)) - }}); - }};"; - blockBuilder.WriteLine(blockFormat, OpenIdRelyingPartyAjaxControlBase.CallbackJSFunctionAsync, discoverUrl); - - blockFormat = @" window.postLoginAssertion = function (positiveAssertion) {{ - $('#{0}')[0].setAttribute('value', positiveAssertion); - if ($('#{1}')[0] && !$('#{1}')[0].value) {{ // popups have no ReturnUrl predefined, but full page LogOn does. - $('#{1}')[0].setAttribute('value', window.parent.location.href); - }} - document.forms[{2}].submit(); - }};"; - blockBuilder.WriteLine( - blockFormat, - additionalOptions.AssertionHiddenFieldId, - additionalOptions.ReturnUrlHiddenFieldId, - additionalOptions.FormKey); - - blockFormat = @" $(function () {{ - var box = document.getElementsByName('openid_identifier')[0]; - initAjaxOpenId(box, {0}, {1}, {2}, {3}, {4}, {5}, - null, // js function to invoke on receiving a positive assertion - {6}, {7}, {8}, {9}, {10}, {11}, {12}, {13}, {14}, {15}, {16}, {17}, - false, // auto postback - null); // PostBackEventReference (unused in MVC) - }});"; - blockBuilder.WriteLine( - blockFormat, - MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenIdTextBox.EmbeddedLogoResourceName)), - MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedSpinnerResourceName)), - MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName)), - MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginFailureResourceName)), - selectorOptions.Throttle, - selectorOptions.Timeout.TotalMilliseconds, - MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnText), - MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnToolTip), - selectorOptions.TextBox.ShowLogOnPostBackButton ? "true" : "false", - MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnPostBackToolTip), - MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.RetryText), - MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.RetryToolTip), - MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.BusyToolTip), - MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.IdentifierRequiredMessage), - MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnInProgressMessage), - MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticationSucceededToolTip), - MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticatedAsToolTip), - MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticationFailedToolTip)); - - result.WriteScriptBlock(blockBuilder.ToString()); - result.WriteScriptTags(OpenId.RelyingParty.OpenIdSelector.EmbeddedScriptResourceName); - - Reporting.RecordFeatureUse("MVC " + typeof(OpenIdSelector).Name); - return result.ToString(); - } - } - } catch { - if (selectorOptionsOwned) { - selectorOptions.Dispose(); - } - - throw; - } - } - - /// <summary> - /// Emits the HTML to render an OpenID Provider button as a part of the overall OpenID Selector UI. - /// </summary> - /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param> - /// <param name="providerIdentifier">The OP Identifier.</param> - /// <param name="imageUrl">The URL of the image to display on the button.</param> - /// <returns> - /// HTML that should be sent directly to the browser. - /// </returns> - public static string OpenIdSelectorOPButton(this HtmlHelper html, Identifier providerIdentifier, string imageUrl) { - Contract.Requires<ArgumentNullException>(html != null); - Contract.Requires<ArgumentNullException>(providerIdentifier != null); - Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(imageUrl)); - Contract.Ensures(Contract.Result<string>() != null); - - return OpenIdSelectorButton(html, providerIdentifier, "OPButton", imageUrl); - } - - /// <summary> - /// Emits the HTML to render a generic OpenID button as a part of the overall OpenID Selector UI, - /// allowing the user to enter their own OpenID. - /// </summary> - /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param> - /// <param name="imageUrl">The URL of the image to display on the button.</param> - /// <returns> - /// HTML that should be sent directly to the browser. - /// </returns> - public static string OpenIdSelectorOpenIdButton(this HtmlHelper html, string imageUrl) { - Contract.Requires<ArgumentNullException>(html != null); - Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(imageUrl)); - Contract.Ensures(Contract.Result<string>() != null); - - return OpenIdSelectorButton(html, "OpenIDButton", "OpenIDButton", imageUrl); - } - - /// <summary> - /// Emits the HTML to render the entire OpenID Selector UI. - /// </summary> - /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param> - /// <param name="buttons">The buttons to include on the selector.</param> - /// <returns> - /// HTML that should be sent directly to the browser. - /// </returns> - [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Not a problem for this type.")] - public static string OpenIdSelector(this HtmlHelper html, params SelectorButton[] buttons) { - Contract.Requires<ArgumentNullException>(html != null); - Contract.Requires<ArgumentNullException>(buttons != null); - Contract.Ensures(Contract.Result<string>() != null); - - using (var writer = new StringWriter(CultureInfo.CurrentCulture)) { - using (var h = new HtmlTextWriter(writer)) { - h.AddAttribute(HtmlTextWriterAttribute.Class, "OpenIdProviders"); - h.RenderBeginTag(HtmlTextWriterTag.Ul); - - foreach (SelectorButton button in buttons) { - var op = button as SelectorProviderButton; - if (op != null) { - h.Write(OpenIdSelectorOPButton(html, op.OPIdentifier, op.Image)); - continue; - } - - var openid = button as SelectorOpenIdButton; - if (openid != null) { - h.Write(OpenIdSelectorOpenIdButton(html, openid.Image)); - continue; - } - - ErrorUtilities.VerifySupported(false, "The {0} button is not yet supported for MVC.", button.GetType().Name); - } - - h.RenderEndTag(); // ul - - if (buttons.OfType<SelectorOpenIdButton>().Any()) { - h.Write(OpenIdAjaxTextBox(html)); - } - } - - return writer.ToString(); - } - } - - /// <summary> - /// Emits the HTML to render the <see cref="OpenIdAjaxTextBox"/> control as a part of the overall - /// OpenID Selector UI. - /// </summary> - /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param> - /// <returns> - /// HTML that should be sent directly to the browser. - /// </returns> - [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "html", Justification = "Breaking change, and it's an extension method so it's useful.")] - public static string OpenIdAjaxTextBox(this HtmlHelper html) { - return @"<div style='display: none' id='OpenIDForm'> - <span class='OpenIdAjaxTextBox' style='display: inline-block; position: relative; font-size: 16px'> - <input name='openid_identifier' id='openid_identifier' size='40' style='padding-left: 18px; border-style: solid; border-width: 1px; border-color: lightgray' /> - </span> - </div>"; - } - - /// <summary> - /// Emits the HTML to render a button as a part of the overall OpenID Selector UI. - /// </summary> - /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param> - /// <param name="id">The value to assign to the HTML id attribute.</param> - /// <param name="cssClass">The value to assign to the HTML class attribute.</param> - /// <param name="imageUrl">The URL of the image to draw on the button.</param> - /// <returns> - /// HTML that should be sent directly to the browser. - /// </returns> - [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Not a problem for this type.")] - private static string OpenIdSelectorButton(this HtmlHelper html, string id, string cssClass, string imageUrl) { - Contract.Requires<ArgumentNullException>(html != null); - Contract.Requires<ArgumentNullException>(id != null); - Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(imageUrl)); - Contract.Ensures(Contract.Result<string>() != null); - - using (var writer = new StringWriter(CultureInfo.CurrentCulture)) { - using (var h = new HtmlTextWriter(writer)) { - h.AddAttribute(HtmlTextWriterAttribute.Id, id); - if (!string.IsNullOrEmpty(cssClass)) { - h.AddAttribute(HtmlTextWriterAttribute.Class, cssClass); - } - h.RenderBeginTag(HtmlTextWriterTag.Li); - - h.AddAttribute(HtmlTextWriterAttribute.Href, "#"); - h.RenderBeginTag(HtmlTextWriterTag.A); - - h.RenderBeginTag(HtmlTextWriterTag.Div); - h.RenderBeginTag(HtmlTextWriterTag.Div); - - h.AddAttribute(HtmlTextWriterAttribute.Src, imageUrl); - h.RenderBeginTag(HtmlTextWriterTag.Img); - h.RenderEndTag(); - - h.AddAttribute(HtmlTextWriterAttribute.Src, Util.GetWebResourceUrl(typeof(OpenIdSelector), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName)); - h.AddAttribute(HtmlTextWriterAttribute.Class, "loginSuccess"); - h.AddAttribute(HtmlTextWriterAttribute.Title, "Authenticated as {0}"); - h.RenderBeginTag(HtmlTextWriterTag.Img); - h.RenderEndTag(); - - h.RenderEndTag(); // div - - h.AddAttribute(HtmlTextWriterAttribute.Class, "ui-widget-overlay"); - h.RenderBeginTag(HtmlTextWriterTag.Div); - h.RenderEndTag(); // div - - h.RenderEndTag(); // div - h.RenderEndTag(); // a - h.RenderEndTag(); // li - } - - return writer.ToString(); - } - } - - /// <summary> - /// Emits <script> tags that import a given set of scripts given their URLs. - /// </summary> - /// <param name="writer">The writer to emit the tags to.</param> - /// <param name="scriptUrls">The locations of the scripts to import.</param> - private static void WriteScriptTagsUrls(this TextWriter writer, IEnumerable<string> scriptUrls) { - Contract.Requires<ArgumentNullException>(writer != null); - Contract.Requires<ArgumentNullException>(scriptUrls != null); - - foreach (string script in scriptUrls) { - writer.WriteLine("<script type='text/javascript' src='{0}'></script>", script); - } - } - - /// <summary> - /// Writes out script tags that import a script from resources embedded in this assembly. - /// </summary> - /// <param name="writer">The writer to emit the tags to.</param> - /// <param name="resourceName">Name of the resource.</param> - private static void WriteScriptTags(this TextWriter writer, string resourceName) { - Contract.Requires<ArgumentNullException>(writer != null); - Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(resourceName)); - - WriteScriptTags(writer, new[] { resourceName }); - } - - /// <summary> - /// Writes out script tags that import scripts from resources embedded in this assembly. - /// </summary> - /// <param name="writer">The writer to emit the tags to.</param> - /// <param name="resourceNames">The resource names.</param> - private static void WriteScriptTags(this TextWriter writer, IEnumerable<string> resourceNames) { - Contract.Requires<ArgumentNullException>(writer != null); - Contract.Requires<ArgumentNullException>(resourceNames != null); - - writer.WriteScriptTagsUrls(resourceNames.Select(r => Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), r))); - } - - /// <summary> - /// Writes a given script block, surrounding it with <script> and CDATA tags. - /// </summary> - /// <param name="writer">The writer to emit the tags to.</param> - /// <param name="script">The script to inline on the page.</param> - private static void WriteScriptBlock(this TextWriter writer, string script) { - Contract.Requires<ArgumentNullException>(writer != null); - Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(script)); - - writer.WriteLine("<script type='text/javascript' language='javascript'><!--"); - writer.WriteLine("//<![CDATA["); - writer.WriteLine(script); - writer.WriteLine("//]]>--></script>"); - } - - /// <summary> - /// Writes a given CSS link. - /// </summary> - /// <param name="writer">The writer to emit the tags to.</param> - /// <param name="resourceName">Name of the resource containing the CSS content.</param> - private static void WriteStylesheetLink(this TextWriter writer, string resourceName) { - Contract.Requires<ArgumentNullException>(writer != null); - Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(resourceName)); - - WriteStylesheetLinkUrl(writer, Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyAjaxControlBase), resourceName)); - } - - /// <summary> - /// Writes a given CSS link. - /// </summary> - /// <param name="writer">The writer to emit the tags to.</param> - /// <param name="stylesheet">The stylesheet to link in.</param> - private static void WriteStylesheetLinkUrl(this TextWriter writer, string stylesheet) { - Contract.Requires<ArgumentNullException>(writer != null); - Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(stylesheet)); - - writer.WriteLine("<link rel='stylesheet' type='text/css' href='{0}' />", stylesheet); - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/Controls.cd b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/Controls.cd deleted file mode 100644 index f96db36..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/Controls.cd +++ /dev/null @@ -1,112 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<ClassDiagram MajorVersion="1" MinorVersion="1"> - <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyAjaxControlBase"> - <Position X="0.5" Y="9.75" Width="3" /> - <Compartments> - <Compartment Name="Fields" Collapsed="true" /> - </Compartments> - <TypeIdentifier> - <HashCode>BARAAAAAAAAAAACQAAAAAAAEAAAgAAAAAQAFAAAAAFk=</HashCode> - <FileName>OpenId\RelyingParty\OpenIdRelyingPartyAjaxControlBase.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdMobileTextBox"> - <Position X="8.5" Y="5.25" Width="2.5" /> - <Compartments> - <Compartment Name="Fields" Collapsed="true" /> - </Compartments> - <TypeIdentifier> - <HashCode>AI0JADgFQRQQDAIw4lAYSEIWCAMZhMVlELAASQIAgSI=</HashCode> - <FileName>OpenId\RelyingParty\OpenIdMobileTextBox.cs</FileName> - </TypeIdentifier> - </Class> - <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdLogin"> - <Position X="6.25" Y="1.25" Width="1.75" /> - <Compartments> - <Compartment Name="Fields" Collapsed="true" /> - </Compartments> - <NestedTypes> - <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdLogin.InPlaceControl" Collapsed="true"> - <TypeIdentifier> - <NewMemberFileName>OpenId\RelyingParty\OpenIdLogin.cs</NewMemberFileName> - </TypeIdentifier> - </Class> - </NestedTypes> - <TypeIdentifier> - <HashCode>gIMgADAIAQEQIJAYOQBSADiQBgiIECk0jQCggdAp4BQ=</HashCode> - <FileName>OpenId\RelyingParty\OpenIdLogin.cs</FileName> - </TypeIdentifier> - </Class> - <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdAjaxTextBox"> - <Position X="3.75" Y="10" Width="2.25" /> - <Compartments> - <Compartment Name="Fields" Collapsed="true" /> - </Compartments> - <TypeIdentifier> - <HashCode>ACBEEbABZzOzAKCYJNOEwM3uSIR5AAOkUFANCQ7DsVs=</HashCode> - <FileName>OpenId\RelyingParty\OpenIdAjaxTextBox.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdButton"> - <Position X="8.75" Y="1" Width="1.75" /> - <Compartments> - <Compartment Name="Fields" Collapsed="true" /> - </Compartments> - <InheritanceLine Type="DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyControlBase" ManuallyRouted="true" FixedFromPoint="true" FixedToPoint="true"> - <Path> - <Point X="2.875" Y="0.5" /> - <Point X="7.194" Y="0.5" /> - <Point X="7.194" Y="1" /> - <Point X="8.75" Y="1" /> - </Path> - </InheritanceLine> - <TypeIdentifier> - <HashCode>BAAEQAAAAAAAAAACAAAgAAAAAIAAAACQABAECABAAAA=</HashCode> - <FileName>OpenId\RelyingParty\OpenIdButton.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdTextBox"> - <Position X="3.5" Y="1.25" Width="2.25" /> - <Compartments> - <Compartment Name="Fields" Collapsed="true" /> - </Compartments> - <TypeIdentifier> - <HashCode>AIEVQjgBIxYITIARcAAACEc2CIAIlER1CBAQSQoEpCg=</HashCode> - <FileName>OpenId\RelyingParty\OpenIdTextBox.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyControlBase"> - <Position X="0.5" Y="0.5" Width="2.5" /> - <Compartments> - <Compartment Name="Fields" Collapsed="true" /> - </Compartments> - <NestedTypes> - <Enum Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyControlBase.LoginSiteNotification" Collapsed="true"> - <TypeIdentifier> - <NewMemberFileName>OpenId\RelyingParty\OpenIdRelyingPartyControlBase.cs</NewMemberFileName> - </TypeIdentifier> - </Enum> - <Enum Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyControlBase.LoginPersistence" Collapsed="true"> - <TypeIdentifier> - <NewMemberFileName>OpenId\RelyingParty\OpenIdRelyingPartyControlBase.cs</NewMemberFileName> - </TypeIdentifier> - </Enum> - <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyControlBase.DuplicateRequestedHostsComparer" Collapsed="true"> - <TypeIdentifier> - <NewMemberFileName>OpenId\RelyingParty\OpenIdRelyingPartyControlBase.cs</NewMemberFileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - </NestedTypes> - <TypeIdentifier> - <HashCode>BA0AAsAAQCAwQAJAoFAWwADSAgE5EIEEEbAGSAwAgfI=</HashCode> - <FileName>OpenId\RelyingParty\OpenIdRelyingPartyControlBase.cs</FileName> - </TypeIdentifier> - <Lollipop Position="0.2" /> - </Class> - <Font Name="Segoe UI" Size="9" /> -</ClassDiagram>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdAjaxRelyingParty.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdAjaxRelyingParty.cs deleted file mode 100644 index 42bfbde..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdAjaxRelyingParty.cs +++ /dev/null @@ -1,242 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdAjaxRelyingParty.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OpenId.RelyingParty { - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Diagnostics.Contracts; - using System.Globalization; - using System.Linq; - using System.Net; - using System.Net.Mime; - using System.Text; - using System.Web; - using System.Web.Script.Serialization; - - using DotNetOpenAuth.Configuration; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OpenId.Extensions; - using DotNetOpenAuth.OpenId.Extensions.UI; - - /// <summary> - /// Provides the programmatic facilities to act as an AJAX-enabled OpenID relying party. - /// </summary> - public class OpenIdAjaxRelyingParty : OpenIdRelyingParty { - /// <summary> - /// Initializes a new instance of the <see cref="OpenIdAjaxRelyingParty"/> class. - /// </summary> - public OpenIdAjaxRelyingParty() { - Reporting.RecordFeatureUse(this); - } - - /// <summary> - /// Initializes a new instance of the <see cref="OpenIdAjaxRelyingParty"/> class. - /// </summary> - /// <param name="applicationStore">The application store. If <c>null</c>, the relying party will always operate in "dumb mode".</param> - public OpenIdAjaxRelyingParty(IOpenIdApplicationStore applicationStore) - : base(applicationStore) { - Reporting.RecordFeatureUse(this); - } - - /// <summary> - /// Generates AJAX-ready authentication requests that can satisfy the requirements of some OpenID Identifier. - /// </summary> - /// <param name="userSuppliedIdentifier">The Identifier supplied by the user. This may be a URL, an XRI or i-name.</param> - /// <param name="realm">The shorest URL that describes this relying party web site's address. - /// For example, if your login page is found at https://www.example.com/login.aspx, - /// your realm would typically be https://www.example.com/.</param> - /// <param name="returnToUrl">The URL of the login page, or the page prepared to receive authentication - /// responses from the OpenID Provider.</param> - /// <returns> - /// A sequence of authentication requests, any of which constitutes a valid identity assertion on the Claimed Identifier. - /// Never null, but may be empty. - /// </returns> - /// <remarks> - /// <para>Any individual generated request can satisfy the authentication. - /// The generated requests are sorted in preferred order. - /// Each request is generated as it is enumerated to. Associations are created only as - /// <see cref="IAuthenticationRequest.RedirectingResponse"/> is called.</para> - /// <para>No exception is thrown if no OpenID endpoints were discovered. - /// An empty enumerable is returned instead.</para> - /// </remarks> - public override IEnumerable<IAuthenticationRequest> CreateRequests(Identifier userSuppliedIdentifier, Realm realm, Uri returnToUrl) { - var requests = base.CreateRequests(userSuppliedIdentifier, realm, returnToUrl); - - // Alter the requests so that have AJAX characteristics. - // 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. - int reqIndex = 0; - foreach (var req in requests) { - // Inform ourselves in return_to that we're in a popup. - req.SetUntrustedCallbackArgument(OpenIdRelyingPartyControlBase.UIPopupCallbackKey, "1"); - - if (req.DiscoveryResult.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(OpenIdRelyingPartyControlBase.PopupUISupportedJSHint, "1"); - } - - req.SetUntrustedCallbackArgument("index", (reqIndex++).ToString(CultureInfo.InvariantCulture)); - - // If the ReturnToUrl was explicitly set, we'll need to reset our first parameter - if (OpenIdElement.Configuration.RelyingParty.PreserveUserSuppliedIdentifier) { - if (string.IsNullOrEmpty(HttpUtility.ParseQueryString(req.ReturnToUrl.Query)[AuthenticationRequest.UserSuppliedIdentifierParameterName])) { - req.SetUntrustedCallbackArgument(AuthenticationRequest.UserSuppliedIdentifierParameterName, userSuppliedIdentifier.OriginalString); - } - } - - // Our javascript needs to let the user know which endpoint responded. So we force it here. - // This gives us the info even for 1.0 OPs and 2.0 setup_required responses. - req.SetUntrustedCallbackArgument(OpenIdRelyingPartyAjaxControlBase.OPEndpointParameterName, req.Provider.Uri.AbsoluteUri); - req.SetUntrustedCallbackArgument(OpenIdRelyingPartyAjaxControlBase.ClaimedIdParameterName, (string)req.ClaimedIdentifier ?? string.Empty); - - // Inform ourselves in return_to that we're in a popup or iframe. - req.SetUntrustedCallbackArgument(OpenIdRelyingPartyAjaxControlBase.UIPopupCallbackKey, "1"); - - // We append a # at the end so that if the OP happens to support it, - // the OpenID response "query string" is appended after the hash rather than before, resulting in the - // browser being super-speedy in closing the popup window since it doesn't try to pull a newer version - // of the static resource down from the server merely because of a changed URL. - // http://www.nabble.com/Re:-Defining-how-OpenID-should-behave-with-fragments-in-the-return_to-url-p22694227.html - ////TODO: - - yield return req; - } - } - - /// <summary> - /// Serializes discovery results on some <i>single</i> identifier on behalf of Javascript running on the browser. - /// </summary> - /// <param name="requests">The discovery results from just <i>one</i> identifier to serialize as a JSON response.</param> - /// <returns> - /// The JSON result to return to the user agent. - /// </returns> - /// <remarks> - /// We prepare a JSON object with this interface: - /// <code> - /// class jsonResponse { - /// string claimedIdentifier; - /// Array requests; // never null - /// string error; // null if no error - /// } - /// </code> - /// Each element in the requests array looks like this: - /// <code> - /// class jsonAuthRequest { - /// string endpoint; // URL to the OP endpoint - /// string immediate; // URL to initiate an immediate request - /// string setup; // URL to initiate a setup request. - /// } - /// </code> - /// </remarks> - public OutgoingWebResponse AsAjaxDiscoveryResult(IEnumerable<IAuthenticationRequest> requests) { - Contract.Requires<ArgumentNullException>(requests != null); - - var serializer = new JavaScriptSerializer(); - return new OutgoingWebResponse { - Body = serializer.Serialize(this.AsJsonDiscoveryResult(requests)), - }; - } - - /// <summary> - /// Serializes discovery on a set of identifiers for preloading into an HTML page that carries - /// an AJAX-aware OpenID control. - /// </summary> - /// <param name="requests">The discovery results to serialize as a JSON response.</param> - /// <returns> - /// The JSON result to return to the user agent. - /// </returns> - public string AsAjaxPreloadedDiscoveryResult(IEnumerable<IAuthenticationRequest> requests) { - Contract.Requires<ArgumentNullException>(requests != null); - - var serializer = new JavaScriptSerializer(); - string json = serializer.Serialize(this.AsJsonPreloadedDiscoveryResult(requests)); - - string script = "window.dnoa_internal.loadPreloadedDiscoveryResults(" + json + ");"; - return script; - } - - /// <summary> - /// Converts a sequence of authentication requests to a JSON object for seeding an AJAX-enabled login page. - /// </summary> - /// <param name="requests">The discovery results from just <i>one</i> identifier to serialize as a JSON response.</param> - /// <returns>A JSON object, not yet serialized.</returns> - internal object AsJsonDiscoveryResult(IEnumerable<IAuthenticationRequest> requests) { - Contract.Requires<ArgumentNullException>(requests != null); - - requests = requests.CacheGeneratedResults(); - - if (requests.Any()) { - return new { - claimedIdentifier = (string)requests.First().ClaimedIdentifier, - requests = requests.Select(req => new { - endpoint = req.Provider.Uri.AbsoluteUri, - immediate = this.GetRedirectUrl(req, true), - setup = this.GetRedirectUrl(req, false), - }).ToArray() - }; - } else { - return new { - requests = new object[0], - error = OpenIdStrings.OpenIdEndpointNotFound, - }; - } - } - - /// <summary> - /// Serializes discovery on a set of identifiers for preloading into an HTML page that carries - /// an AJAX-aware OpenID control. - /// </summary> - /// <param name="requests">The discovery results to serialize as a JSON response.</param> - /// <returns> - /// A JSON object, not yet serialized to a string. - /// </returns> - private object AsJsonPreloadedDiscoveryResult(IEnumerable<IAuthenticationRequest> requests) { - Contract.Requires<ArgumentNullException>(requests != null); - - // We prepare a JSON object with this interface: - // Array discoveryWrappers; - // Where each element in the above array has this interface: - // class discoveryWrapper { - // string userSuppliedIdentifier; - // jsonResponse discoveryResult; // contains result of call to SerializeDiscoveryAsJson(Identifier) - // } - var json = (from request in requests - group request by request.DiscoveryResult.UserSuppliedIdentifier into requestsByIdentifier - select new { - userSuppliedIdentifier = (string)requestsByIdentifier.Key, - discoveryResult = this.AsJsonDiscoveryResult(requestsByIdentifier), - }).ToArray(); - - return json; - } - - /// <summary> - /// Gets the full URL that carries an OpenID message, even if it exceeds the normal maximum size of a URL, - /// for purposes of sending to an AJAX component running in the browser. - /// </summary> - /// <param name="request">The authentication request.</param> - /// <param name="immediate"><c>true</c>to create a checkid_immediate request; - /// <c>false</c> to create a checkid_setup request.</param> - /// <returns>The absolute URL that carries the entire OpenID message.</returns> - private Uri GetRedirectUrl(IAuthenticationRequest request, bool immediate) { - Contract.Requires<ArgumentNullException>(request != null); - - request.Mode = immediate ? AuthenticationRequestMode.Immediate : AuthenticationRequestMode.Setup; - return request.RedirectingResponse.GetDirectUriRequest(this.Channel); - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdAjaxTextBox.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdAjaxTextBox.cs deleted file mode 100644 index 8be097f..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdAjaxTextBox.cs +++ /dev/null @@ -1,877 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdAjaxTextBox.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -[assembly: System.Web.UI.WebResource(DotNetOpenAuth.OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedScriptResourceName, "text/javascript")] -[assembly: System.Web.UI.WebResource(DotNetOpenAuth.OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedStylesheetResourceName, "text/css")] -[assembly: System.Web.UI.WebResource(DotNetOpenAuth.OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedSpinnerResourceName, "image/gif")] -[assembly: System.Web.UI.WebResource(DotNetOpenAuth.OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName, "image/png")] -[assembly: System.Web.UI.WebResource(DotNetOpenAuth.OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginFailureResourceName, "image/png")] - -#pragma warning disable 0809 // marking inherited, unsupported properties as obsolete to discourage their use - -namespace DotNetOpenAuth.OpenId.RelyingParty { - using System; - using System.Collections.Generic; - using System.Collections.Specialized; - using System.ComponentModel; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.Diagnostics.Contracts; - using System.Drawing.Design; - using System.Globalization; - using System.Text; - using System.Web.UI; - using System.Web.UI.HtmlControls; - using DotNetOpenAuth.Messaging; - - /// <summary> - /// An ASP.NET control that provides a minimal text box that is OpenID-aware and uses AJAX for - /// a premium login experience. - /// </summary> - [DefaultProperty("Text"), ValidationProperty("Text")] - [ToolboxData("<{0}:OpenIdAjaxTextBox runat=\"server\" />")] - public class OpenIdAjaxTextBox : OpenIdRelyingPartyAjaxControlBase, IEditableTextControl, ITextControl, IPostBackDataHandler { - /// <summary> - /// The name of the manifest stream containing the OpenIdAjaxTextBox.js file. - /// </summary> - internal const string EmbeddedScriptResourceName = Util.DefaultNamespace + ".OpenId.RelyingParty.OpenIdAjaxTextBox.js"; - - /// <summary> - /// The name of the manifest stream containing the OpenIdAjaxTextBox.css file. - /// </summary> - internal const string EmbeddedStylesheetResourceName = Util.DefaultNamespace + ".OpenId.RelyingParty.OpenIdAjaxTextBox.css"; - - /// <summary> - /// The name of the manifest stream containing the spinner.gif file. - /// </summary> - internal const string EmbeddedSpinnerResourceName = Util.DefaultNamespace + ".OpenId.RelyingParty.spinner.gif"; - - /// <summary> - /// The name of the manifest stream containing the login_success.png file. - /// </summary> - internal const string EmbeddedLoginSuccessResourceName = Util.DefaultNamespace + ".OpenId.RelyingParty.login_success.png"; - - /// <summary> - /// The name of the manifest stream containing the login_failure.png file. - /// </summary> - internal const string EmbeddedLoginFailureResourceName = Util.DefaultNamespace + ".OpenId.RelyingParty.login_failure.png"; - - /// <summary> - /// The default value for the <see cref="DownloadYahooUILibrary"/> property. - /// </summary> - internal const bool DownloadYahooUILibraryDefault = true; - - /// <summary> - /// The default value for the <see cref="Throttle"/> property. - /// </summary> - internal const int ThrottleDefault = 3; - - #region Property viewstate keys - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="AutoPostBack"/> property. - /// </summary> - private const string AutoPostBackViewStateKey = "AutoPostback"; - - /// <summary> - /// The viewstate key to use for the <see cref="Text"/> property. - /// </summary> - private const string TextViewStateKey = "Text"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="Columns"/> property. - /// </summary> - private const string ColumnsViewStateKey = "Columns"; - - /// <summary> - /// The viewstate key to use for the <see cref="CssClass"/> property. - /// </summary> - private const string CssClassViewStateKey = "CssClass"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="OnClientAssertionReceived"/> property. - /// </summary> - private const string OnClientAssertionReceivedViewStateKey = "OnClientAssertionReceived"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="AuthenticatedAsToolTip"/> property. - /// </summary> - private const string AuthenticatedAsToolTipViewStateKey = "AuthenticatedAsToolTip"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="AuthenticationSucceededToolTip"/> property. - /// </summary> - private const string AuthenticationSucceededToolTipViewStateKey = "AuthenticationSucceededToolTip"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="LogOnInProgressMessage"/> property. - /// </summary> - private const string LogOnInProgressMessageViewStateKey = "BusyToolTip"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="AuthenticationFailedToolTip"/> property. - /// </summary> - private const string AuthenticationFailedToolTipViewStateKey = "AuthenticationFailedToolTip"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="IdentifierRequiredMessage"/> property. - /// </summary> - private const string IdentifierRequiredMessageViewStateKey = "BusyToolTip"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="BusyToolTip"/> property. - /// </summary> - private const string BusyToolTipViewStateKey = "BusyToolTip"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="LogOnText"/> property. - /// </summary> - private const string LogOnTextViewStateKey = "LoginText"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="Throttle"/> property. - /// </summary> - private const string ThrottleViewStateKey = "Throttle"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="LogOnToolTip"/> property. - /// </summary> - private const string LogOnToolTipViewStateKey = "LoginToolTip"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="LogOnPostBackToolTip"/> property. - /// </summary> - private const string LogOnPostBackToolTipViewStateKey = "LoginPostBackToolTip"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="Name"/> property. - /// </summary> - private const string NameViewStateKey = "Name"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="Timeout"/> property. - /// </summary> - private const string TimeoutViewStateKey = "Timeout"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="TabIndex"/> property. - /// </summary> - private const string TabIndexViewStateKey = "TabIndex"; - - /// <summary> - /// The viewstate key to use for the <see cref="Enabled"/> property. - /// </summary> - private const string EnabledViewStateKey = "Enabled"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="RetryToolTip"/> property. - /// </summary> - private const string RetryToolTipViewStateKey = "RetryToolTip"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="RetryText"/> property. - /// </summary> - private const string RetryTextViewStateKey = "RetryText"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="DownloadYahooUILibrary"/> property. - /// </summary> - private const string DownloadYahooUILibraryViewStateKey = "DownloadYahooUILibrary"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="ShowLogOnPostBackButton"/> property. - /// </summary> - private const string ShowLogOnPostBackButtonViewStateKey = "ShowLogOnPostBackButton"; - - #endregion - - #region Property defaults - - /// <summary> - /// The default value for the <see cref="AutoPostBack"/> property. - /// </summary> - private const bool AutoPostBackDefault = false; - - /// <summary> - /// The default value for the <see cref="Columns"/> property. - /// </summary> - private const int ColumnsDefault = 40; - - /// <summary> - /// The default value for the <see cref="CssClass"/> property. - /// </summary> - private const string CssClassDefault = "openid"; - - /// <summary> - /// The default value for the <see cref="LogOnInProgressMessage"/> property. - /// </summary> - private const string LogOnInProgressMessageDefault = "Please wait for login to complete."; - - /// <summary> - /// The default value for the <see cref="AuthenticationSucceededToolTip"/> property. - /// </summary> - private const string AuthenticationSucceededToolTipDefault = "Authenticated by {0}."; - - /// <summary> - /// The default value for the <see cref="AuthenticatedAsToolTip"/> property. - /// </summary> - private const string AuthenticatedAsToolTipDefault = "Authenticated as {0}."; - - /// <summary> - /// The default value for the <see cref="AuthenticationFailedToolTip"/> property. - /// </summary> - private const string AuthenticationFailedToolTipDefault = "Authentication failed."; - - /// <summary> - /// The default value for the <see cref="LogOnText"/> property. - /// </summary> - private const string LogOnTextDefault = "LOG IN"; - - /// <summary> - /// The default value for the <see cref="BusyToolTip"/> property. - /// </summary> - private const string BusyToolTipDefault = "Discovering/authenticating"; - - /// <summary> - /// The default value for the <see cref="IdentifierRequiredMessage"/> property. - /// </summary> - private const string IdentifierRequiredMessageDefault = "Please correct errors in OpenID identifier and allow login to complete before submitting."; - - /// <summary> - /// The default value for the <see cref="Name"/> property. - /// </summary> - private const string NameDefault = "openid_identifier"; - - /// <summary> - /// Default value for <see cref="TabIndex"/> property. - /// </summary> - private const short TabIndexDefault = 0; - - /// <summary> - /// The default value for the <see cref="RetryToolTip"/> property. - /// </summary> - private const string RetryToolTipDefault = "Retry a failed identifier discovery."; - - /// <summary> - /// The default value for the <see cref="LogOnToolTip"/> property. - /// </summary> - private const string LogOnToolTipDefault = "Click here to log in using a pop-up window."; - - /// <summary> - /// The default value for the <see cref="LogOnPostBackToolTip"/> property. - /// </summary> - private const string LogOnPostBackToolTipDefault = "Click here to log in immediately."; - - /// <summary> - /// The default value for the <see cref="RetryText"/> property. - /// </summary> - private const string RetryTextDefault = "RETRY"; - - /// <summary> - /// The default value for the <see cref="ShowLogOnPostBackButton"/> property. - /// </summary> - private const bool ShowLogOnPostBackButtonDefault = false; - - #endregion - - /// <summary> - /// The path where the YUI control library should be downloaded from for HTTP pages. - /// </summary> - private const string YuiLoaderHttp = "http://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/yuiloader/yuiloader-min.js"; - - /// <summary> - /// The path where the YUI control library should be downloaded from for HTTPS pages. - /// </summary> - private const string YuiLoaderHttps = "https://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/yuiloader/yuiloader-min.js"; - - /// <summary> - /// Initializes a new instance of the <see cref="OpenIdAjaxTextBox"/> class. - /// </summary> - public OpenIdAjaxTextBox() { - this.HookFormSubmit = true; - } - - #region Events - - /// <summary> - /// Fired when the content of the text changes between posts to the server. - /// </summary> - [Description("Occurs when the content of the text changes between posts to the server."), Category(BehaviorCategory)] - public event EventHandler TextChanged; - - /// <summary> - /// Gets or sets the client-side script that executes when an authentication - /// assertion is received (but before it is verified). - /// </summary> - /// <remarks> - /// <para>In the context of the executing javascript set in this property, the - /// local variable <i>sender</i> is set to the openid_identifier input box - /// that is executing this code. - /// This variable has a getClaimedIdentifier() method that may be used to - /// identify the user who is being authenticated.</para> - /// <para>It is <b>very</b> important to note that when this code executes, - /// the authentication has not been verified and may have been spoofed. - /// No security-sensitive operations should take place in this javascript code. - /// The authentication is verified on the server by the time the - /// <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> server-side event fires.</para> - /// </remarks> - [Description("Gets or sets the client-side script that executes when an authentication assertion is received (but before it is verified).")] - [Bindable(true), DefaultValue(""), Category(BehaviorCategory)] - public string OnClientAssertionReceived { - get { return this.ViewState[OnClientAssertionReceivedViewStateKey] as string; } - set { this.ViewState[OnClientAssertionReceivedViewStateKey] = value; } - } - - #endregion - - #region Properties - - /// <summary> - /// Gets or sets the value in the text field, completely unprocessed or normalized. - /// </summary> - [Bindable(true), DefaultValue(""), Category(AppearanceCategory)] - [Description("The content of the text box.")] - public string Text { - get { - return this.Identifier != null ? this.Identifier.OriginalString : (this.ViewState[TextViewStateKey] as string ?? string.Empty); - } - - set { - // Try to store it as a validated identifier, - // but failing that at least store the text. - Identifier id; - if (Identifier.TryParse(value, out id)) { - this.Identifier = id; - } else { - // Be sure to set the viewstate AFTER setting the Identifier, - // since setting the Identifier clears the viewstate in OnIdentifierChanged. - this.Identifier = null; - this.ViewState[TextViewStateKey] = value; - } - } - } - - /// <summary> - /// Gets or sets a value indicating whether a postback is made to fire the - /// <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event as soon as authentication has completed - /// successfully. - /// </summary> - /// <value> - /// <c>true</c> if a postback should be made automatically upon authentication; - /// otherwise, <c>false</c> to delay the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> - /// event from firing at the server until a postback is made by some other control. - /// </value> - [Bindable(true), Category(BehaviorCategory), DefaultValue(AutoPostBackDefault)] - [Description("Whether the LoggedIn event fires on the server as soon as authentication completes successfully.")] - public bool AutoPostBack { - get { return (bool)(this.ViewState[AutoPostBackViewStateKey] ?? AutoPostBackDefault); } - set { this.ViewState[AutoPostBackViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the width of the text box in characters. - /// </summary> - [Bindable(true), Category(AppearanceCategory), DefaultValue(ColumnsDefault)] - [Description("The width of the text box in characters.")] - public int Columns { - get { - return (int)(this.ViewState[ColumnsViewStateKey] ?? ColumnsDefault); - } - - set { - Contract.Requires<ArgumentOutOfRangeException>(value >= 0); - this.ViewState[ColumnsViewStateKey] = value; - } - } - - /// <summary> - /// Gets or sets the CSS class assigned to the text box. - /// </summary> - [Bindable(true), DefaultValue(CssClassDefault), Category(AppearanceCategory)] - [Description("The CSS class assigned to the text box.")] - public string CssClass { - get { return (string)this.ViewState[CssClassViewStateKey]; } - set { this.ViewState[CssClassViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the tab index of the text box control. Use 0 to omit an explicit tabindex. - /// </summary> - [Bindable(true), Category(BehaviorCategory), DefaultValue(TabIndexDefault)] - [Description("The tab index of the text box control. Use 0 to omit an explicit tabindex.")] - public virtual short TabIndex { - get { return (short)(this.ViewState[TabIndexViewStateKey] ?? TabIndexDefault); } - set { this.ViewState[TabIndexViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets a value indicating whether this <see cref="OpenIdTextBox"/> is enabled - /// in the browser for editing and will respond to incoming OpenID messages. - /// </summary> - /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value> - [Bindable(true), DefaultValue(true), Category(BehaviorCategory)] - [Description("Whether the control is editable in the browser and will respond to OpenID messages.")] - public bool Enabled { - get { return (bool)(this.ViewState[EnabledViewStateKey] ?? true); } - set { this.ViewState[EnabledViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the HTML name to assign to the text field. - /// </summary> - [Bindable(true), DefaultValue(NameDefault), Category("Misc")] - [Description("The HTML name to assign to the text field.")] - public string Name { - get { - return (string)(this.ViewState[NameViewStateKey] ?? NameDefault); - } - - set { - Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(value)); - this.ViewState[NameViewStateKey] = value ?? string.Empty; - } - } - - /// <summary> - /// Gets or sets the time duration for the AJAX control to wait for an OP to respond before reporting failure to the user. - /// </summary> - [Browsable(true), DefaultValue(typeof(TimeSpan), "00:00:08"), Category(BehaviorCategory)] - [Description("The time duration for the AJAX control to wait for an OP to respond before reporting failure to the user.")] - public TimeSpan Timeout { - get { - return (TimeSpan)(this.ViewState[TimeoutViewStateKey] ?? TimeoutDefault); - } - - set { - Contract.Requires<ArgumentOutOfRangeException>(value.TotalMilliseconds > 0); - this.ViewState[TimeoutViewStateKey] = value; - } - } - - /// <summary> - /// Gets or sets the maximum number of OpenID Providers to simultaneously try to authenticate with. - /// </summary> - [Browsable(true), DefaultValue(ThrottleDefault), Category(BehaviorCategory)] - [Description("The maximum number of OpenID Providers to simultaneously try to authenticate with.")] - public int Throttle { - get { - return (int)(this.ViewState[ThrottleViewStateKey] ?? ThrottleDefault); - } - - set { - Contract.Requires<ArgumentOutOfRangeException>(value > 0); - this.ViewState[ThrottleViewStateKey] = value; - } - } - - /// <summary> - /// Gets or sets the text that appears on the LOG IN button in cases where immediate (invisible) authentication fails. - /// </summary> - [Bindable(true), DefaultValue(LogOnTextDefault), Localizable(true), Category(AppearanceCategory)] - [Description("The text that appears on the LOG IN button in cases where immediate (invisible) authentication fails.")] - public string LogOnText { - get { - return (string)(this.ViewState[LogOnTextViewStateKey] ?? LogOnTextDefault); - } - - set { - Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(value)); - this.ViewState[LogOnTextViewStateKey] = value ?? string.Empty; - } - } - - /// <summary> - /// Gets or sets the rool tip text that appears on the LOG IN button in cases where immediate (invisible) authentication fails. - /// </summary> - [Bindable(true), DefaultValue(LogOnToolTipDefault), Localizable(true), Category(AppearanceCategory)] - [Description("The tool tip text that appears on the LOG IN button in cases where immediate (invisible) authentication fails.")] - public string LogOnToolTip { - get { return (string)(this.ViewState[LogOnToolTipViewStateKey] ?? LogOnToolTipDefault); } - set { this.ViewState[LogOnToolTipViewStateKey] = value ?? string.Empty; } - } - - /// <summary> - /// Gets or sets the rool tip text that appears on the LOG IN button when clicking the button will result in an immediate postback. - /// </summary> - [Bindable(true), DefaultValue(LogOnPostBackToolTipDefault), Localizable(true), Category(AppearanceCategory)] - [Description("The tool tip text that appears on the LOG IN button when clicking the button will result in an immediate postback.")] - public string LogOnPostBackToolTip { - get { return (string)(this.ViewState[LogOnPostBackToolTipViewStateKey] ?? LogOnPostBackToolTipDefault); } - set { this.ViewState[LogOnPostBackToolTipViewStateKey] = value ?? string.Empty; } - } - - /// <summary> - /// Gets or sets the text that appears on the RETRY button in cases where authentication times out. - /// </summary> - [Bindable(true), DefaultValue(RetryTextDefault), Localizable(true), Category(AppearanceCategory)] - [Description("The text that appears on the RETRY button in cases where authentication times out.")] - public string RetryText { - get { - return (string)(this.ViewState[RetryTextViewStateKey] ?? RetryTextDefault); - } - - set { - Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(value)); - this.ViewState[RetryTextViewStateKey] = value ?? string.Empty; - } - } - - /// <summary> - /// Gets or sets the tool tip text that appears on the RETRY button in cases where authentication times out. - /// </summary> - [Bindable(true), DefaultValue(RetryToolTipDefault), Localizable(true), Category(AppearanceCategory)] - [Description("The tool tip text that appears on the RETRY button in cases where authentication times out.")] - public string RetryToolTip { - get { return (string)(this.ViewState[RetryToolTipViewStateKey] ?? RetryToolTipDefault); } - set { this.ViewState[RetryToolTipViewStateKey] = value ?? string.Empty; } - } - - /// <summary> - /// Gets or sets the tool tip text that appears when authentication succeeds. - /// </summary> - [Bindable(true), DefaultValue(AuthenticationSucceededToolTipDefault), Localizable(true), Category(AppearanceCategory)] - [Description("The tool tip text that appears when authentication succeeds.")] - public string AuthenticationSucceededToolTip { - get { return (string)(this.ViewState[AuthenticationSucceededToolTipViewStateKey] ?? AuthenticationSucceededToolTipDefault); } - set { this.ViewState[AuthenticationSucceededToolTipViewStateKey] = value ?? string.Empty; } - } - - /// <summary> - /// Gets or sets the tool tip text that appears on the green checkmark when authentication succeeds. - /// </summary> - [Bindable(true), DefaultValue(AuthenticatedAsToolTipDefault), Localizable(true), Category(AppearanceCategory)] - [Description("The tool tip text that appears on the green checkmark when authentication succeeds.")] - public string AuthenticatedAsToolTip { - get { return (string)(this.ViewState[AuthenticatedAsToolTipViewStateKey] ?? AuthenticatedAsToolTipDefault); } - set { this.ViewState[AuthenticatedAsToolTipViewStateKey] = value ?? string.Empty; } - } - - /// <summary> - /// Gets or sets the tool tip text that appears when authentication fails. - /// </summary> - [Bindable(true), DefaultValue(AuthenticationFailedToolTipDefault), Localizable(true), Category(AppearanceCategory)] - [Description("The tool tip text that appears when authentication fails.")] - public string AuthenticationFailedToolTip { - get { return (string)(this.ViewState[AuthenticationFailedToolTipViewStateKey] ?? AuthenticationFailedToolTipDefault); } - set { this.ViewState[AuthenticationFailedToolTipViewStateKey] = value ?? string.Empty; } - } - - /// <summary> - /// Gets or sets the tool tip text that appears over the text box when it is discovering and authenticating. - /// </summary> - [Bindable(true), DefaultValue(BusyToolTipDefault), Localizable(true), Category(AppearanceCategory)] - [Description("The tool tip text that appears over the text box when it is discovering and authenticating.")] - public string BusyToolTip { - get { return (string)(this.ViewState[BusyToolTipViewStateKey] ?? BusyToolTipDefault); } - set { this.ViewState[BusyToolTipViewStateKey] = value ?? string.Empty; } - } - - /// <summary> - /// Gets or sets the message that is displayed if a postback is about to occur before the identifier has been supplied. - /// </summary> - [Bindable(true), DefaultValue(IdentifierRequiredMessageDefault), Localizable(true), Category(AppearanceCategory)] - [Description("The message that is displayed if a postback is about to occur before the identifier has been supplied.")] - public string IdentifierRequiredMessage { - get { return (string)(this.ViewState[IdentifierRequiredMessageViewStateKey] ?? IdentifierRequiredMessageDefault); } - set { this.ViewState[IdentifierRequiredMessageViewStateKey] = value ?? string.Empty; } - } - - /// <summary> - /// Gets or sets the message that is displayed if a postback is attempted while login is in process. - /// </summary> - [Bindable(true), DefaultValue(LogOnInProgressMessageDefault), Localizable(true), Category(AppearanceCategory)] - [Description("The message that is displayed if a postback is attempted while login is in process.")] - public string LogOnInProgressMessage { - get { return (string)(this.ViewState[LogOnInProgressMessageViewStateKey] ?? LogOnInProgressMessageDefault); } - set { this.ViewState[LogOnInProgressMessageViewStateKey] = value ?? string.Empty; } - } - - /// <summary> - /// Gets or sets a value indicating whether the Yahoo! User Interface Library (YUI) - /// will be downloaded in order to provide a login split button. - /// </summary> - /// <value> - /// <c>true</c> to use a split button; otherwise, <c>false</c> to use a standard HTML button - /// or a split button by downloading the YUI library yourself on the hosting web page. - /// </value> - /// <remarks> - /// The split button brings in about 180KB of YUI javascript dependencies. - /// </remarks> - [Bindable(true), DefaultValue(DownloadYahooUILibraryDefault), Category(BehaviorCategory)] - [Description("Whether a split button will be used for the \"log in\" when the user provides an identifier that delegates to more than one Provider.")] - public bool DownloadYahooUILibrary { - get { return (bool)(this.ViewState[DownloadYahooUILibraryViewStateKey] ?? DownloadYahooUILibraryDefault); } - set { this.ViewState[DownloadYahooUILibraryViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets a value indicating whether the "Log in" button will be shown - /// to initiate a postback containing the positive assertion. - /// </summary> - [Bindable(true), DefaultValue(ShowLogOnPostBackButtonDefault), Category(AppearanceCategory)] - [Description("Whether the log in button will be shown to initiate a postback containing the positive assertion.")] - public bool ShowLogOnPostBackButton { - get { return (bool)(this.ViewState[ShowLogOnPostBackButtonViewStateKey] ?? ShowLogOnPostBackButtonDefault); } - set { this.ViewState[ShowLogOnPostBackButtonViewStateKey] = value; } - } - - #endregion - - /// <summary> - /// Gets or sets a value indicating whether the ajax text box should hook the form's submit event for special behavior. - /// </summary> - internal bool HookFormSubmit { get; set; } - - /// <summary> - /// Gets the name of the open id auth data form key. - /// </summary> - /// <value> - /// A concatenation of <see cref="Name"/> and <c>"_openidAuthData"</c>. - /// </value> - protected override string OpenIdAuthDataFormKey { - get { return this.Name + "_openidAuthData"; } - } - - /// <summary> - /// Gets the default value for the <see cref="Timeout"/> property. - /// </summary> - /// <value>8 seconds; or eternity if the debugger is attached.</value> - private static TimeSpan TimeoutDefault { - get { - if (Debugger.IsAttached) { - Logger.OpenId.Warn("Debugger is attached. Inflating default OpenIdAjaxTextbox.Timeout value to infinity."); - return TimeSpan.MaxValue; - } else { - return TimeSpan.FromSeconds(8); - } - } - } - - #region IPostBackDataHandler Members - - /// <summary> - /// When implemented by a class, processes postback data for an ASP.NET server control. - /// </summary> - /// <param name="postDataKey">The key identifier for the control.</param> - /// <param name="postCollection">The collection of all incoming name values.</param> - /// <returns> - /// true if the server control's state changes as a result of the postback; otherwise, false. - /// </returns> - bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection) { - return this.LoadPostData(postDataKey, postCollection); - } - - /// <summary> - /// When implemented by a class, signals the server control to notify the ASP.NET application that the state of the control has changed. - /// </summary> - void IPostBackDataHandler.RaisePostDataChangedEvent() { - this.RaisePostDataChangedEvent(); - } - - #endregion - - /// <summary> - /// Raises the <see cref="E:Load"/> event. - /// </summary> - /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> - protected override void OnLoad(EventArgs e) { - base.OnLoad(e); - - this.Page.RegisterRequiresPostBack(this); - } - - /// <summary> - /// Called when the <see cref="Identifier"/> property is changed. - /// </summary> - protected override void OnIdentifierChanged() { - this.ViewState.Remove(TextViewStateKey); - base.OnIdentifierChanged(); - } - - /// <summary> - /// Prepares to render the control. - /// </summary> - /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param> - protected override void OnPreRender(EventArgs e) { - base.OnPreRender(e); - - if (!this.Visible) { - return; - } - - if (this.DownloadYahooUILibrary) { - // Although we'll add the <script> tag to download the YAHOO component, - // a download failure may have occurred, so protect ourselves from a - // script error using an if (YAHOO) block. But apparently at least in IE - // that's not even enough, so we use a try/catch. - string yuiLoadScript = @"try { if (YAHOO) { - var loader = new YAHOO.util.YUILoader({ - require: ['button', 'menu'], - loadOptional: false, - combine: true - }); - - loader.insert(); -} } catch (e) { }"; - this.Page.ClientScript.RegisterClientScriptInclude("yuiloader", this.Page.Request.Url.IsTransportSecure() ? YuiLoaderHttps : YuiLoaderHttp); - this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "requiredYuiComponents", yuiLoadScript, true); - } - - var css = new HtmlLink(); - try { - css.Href = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), EmbeddedStylesheetResourceName); - css.Attributes["rel"] = "stylesheet"; - css.Attributes["type"] = "text/css"; - ErrorUtilities.VerifyHost(this.Page.Header != null, OpenIdStrings.HeadTagMustIncludeRunatServer); - this.Page.Header.Controls.AddAt(0, css); // insert at top so host page can override - } catch { - css.Dispose(); - throw; - } - - this.PrepareClientJavascript(); - - // If an Identifier is preset on this control, preload discovery on that identifier, - // but only if we're not already persisting an authentication result since that would - // be redundant. - if (this.Identifier != null && this.AuthenticationResponse == null) { - this.PreloadDiscovery(this.Identifier); - } - } - - /// <summary> - /// Renders the control. - /// </summary> - /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the control content.</param> - protected override void Render(HtmlTextWriter writer) { - base.Render(writer); - - // We surround the textbox with a span so that the .js file can inject a - // login button within the text box with easy placement. - string css = this.CssClass ?? string.Empty; - css += " OpenIdAjaxTextBox"; - writer.AddAttribute(HtmlTextWriterAttribute.Class, css); - - writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "inline-block"); - writer.AddStyleAttribute(HtmlTextWriterStyle.Position, "relative"); - writer.AddStyleAttribute(HtmlTextWriterStyle.FontSize, "16px"); - writer.RenderBeginTag(HtmlTextWriterTag.Span); - - writer.AddAttribute(HtmlTextWriterAttribute.Name, this.Name); - writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID); - writer.AddAttribute(HtmlTextWriterAttribute.Size, this.Columns.ToString(CultureInfo.InvariantCulture)); - if (!string.IsNullOrEmpty(this.Text)) { - writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Text, true); - } - - if (this.TabIndex > 0) { - writer.AddAttribute(HtmlTextWriterAttribute.Tabindex, this.TabIndex.ToString(CultureInfo.InvariantCulture)); - } - if (!this.Enabled) { - writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "true"); - } - if (!string.IsNullOrEmpty(this.CssClass)) { - writer.AddAttribute(HtmlTextWriterAttribute.Class, this.CssClass); - } - writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingLeft, "18px"); - writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "solid"); - writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "1px"); - writer.AddStyleAttribute(HtmlTextWriterStyle.BorderColor, "lightgray"); - writer.RenderBeginTag(HtmlTextWriterTag.Input); - writer.RenderEndTag(); // </input> - writer.RenderEndTag(); // </span> - } - - /// <summary> - /// When implemented by a class, processes postback data for an ASP.NET server control. - /// </summary> - /// <param name="postDataKey">The key identifier for the control.</param> - /// <param name="postCollection">The collection of all incoming name values.</param> - /// <returns> - /// true if the server control's state changes as a result of the postback; otherwise, false. - /// </returns> - protected virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection) { - // If the control was temporarily hidden, it won't be in the Form data, - // and we'll just implicitly keep the last Text setting. - if (postCollection[this.Name] != null) { - Identifier identifier = postCollection[this.Name].Length == 0 ? null : postCollection[this.Name]; - if (identifier != this.Identifier) { - this.Identifier = identifier; - return true; - } - } - - return false; - } - - /// <summary> - /// When implemented by a class, signals the server control to notify the ASP.NET application that the state of the control has changed. - /// </summary> - [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "Predefined signature.")] - protected virtual void RaisePostDataChangedEvent() { - this.OnTextChanged(); - } - - /// <summary> - /// Called on a postback when the Text property has changed. - /// </summary> - protected virtual void OnTextChanged() { - EventHandler textChanged = this.TextChanged; - if (textChanged != null) { - textChanged(this, EventArgs.Empty); - } - } - - /// <summary> - /// Assembles the javascript to send to the client and registers it with ASP.NET for transmission. - /// </summary> - private void PrepareClientJavascript() { - // Import the .js file where most of the code is. - this.Page.ClientScript.RegisterClientScriptResource(typeof(OpenIdAjaxTextBox), EmbeddedScriptResourceName); - - // Call into the .js file with initialization information. - StringBuilder startupScript = new StringBuilder(); - startupScript.AppendFormat("var box = document.getElementsByName('{0}')[0];{1}", this.Name, Environment.NewLine); - startupScript.AppendFormat( - CultureInfo.InvariantCulture, - "initAjaxOpenId(box, {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}, {13}, {14}, {15}, {16}, {17}, {18}, {19}, function() {{{20};}});{21}", - MessagingUtilities.GetSafeJavascriptValue(this.Page.ClientScript.GetWebResourceUrl(this.GetType(), OpenIdTextBox.EmbeddedLogoResourceName)), - MessagingUtilities.GetSafeJavascriptValue(this.Page.ClientScript.GetWebResourceUrl(this.GetType(), EmbeddedSpinnerResourceName)), - MessagingUtilities.GetSafeJavascriptValue(this.Page.ClientScript.GetWebResourceUrl(this.GetType(), EmbeddedLoginSuccessResourceName)), - MessagingUtilities.GetSafeJavascriptValue(this.Page.ClientScript.GetWebResourceUrl(this.GetType(), EmbeddedLoginFailureResourceName)), - this.Throttle, - this.Timeout.TotalMilliseconds, - string.IsNullOrEmpty(this.OnClientAssertionReceived) ? "null" : "'" + this.OnClientAssertionReceived.Replace(@"\", @"\\").Replace("'", @"\'") + "'", - MessagingUtilities.GetSafeJavascriptValue(this.LogOnText), - MessagingUtilities.GetSafeJavascriptValue(this.LogOnToolTip), - this.ShowLogOnPostBackButton ? "true" : "false", - MessagingUtilities.GetSafeJavascriptValue(this.LogOnPostBackToolTip), - MessagingUtilities.GetSafeJavascriptValue(this.RetryText), - MessagingUtilities.GetSafeJavascriptValue(this.RetryToolTip), - MessagingUtilities.GetSafeJavascriptValue(this.BusyToolTip), - MessagingUtilities.GetSafeJavascriptValue(this.IdentifierRequiredMessage), - MessagingUtilities.GetSafeJavascriptValue(this.LogOnInProgressMessage), - MessagingUtilities.GetSafeJavascriptValue(this.AuthenticationSucceededToolTip), - MessagingUtilities.GetSafeJavascriptValue(this.AuthenticatedAsToolTip), - MessagingUtilities.GetSafeJavascriptValue(this.AuthenticationFailedToolTip), - this.AutoPostBack ? "true" : "false", - Page.ClientScript.GetPostBackEventReference(this, null), - Environment.NewLine); - - ScriptManager.RegisterStartupScript(this, this.GetType(), "ajaxstartup", startupScript.ToString(), true); - if (this.HookFormSubmit) { - string htmlFormat = @" -var openidbox = document.getElementsByName('{0}')[0]; -if (!openidbox.dnoi_internal.onSubmit()) {{ return false; }} -"; - Page.ClientScript.RegisterOnSubmitStatement( - this.GetType(), - "loginvalidation", - string.Format(CultureInfo.InvariantCulture, htmlFormat, this.Name)); - } - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdAjaxTextBox.css b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdAjaxTextBox.css deleted file mode 100644 index bed2e79..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdAjaxTextBox.css +++ /dev/null @@ -1,49 +0,0 @@ -.OpenIdAjaxTextBox input -{ - margin: 0px; -} - -.OpenIdAjaxTextBox > span -{ - position: absolute; - right: -1px; - top: 2px; -} - -.OpenIdAjaxTextBox input[type=button] -{ - visibility: hidden; - position: absolute; - padding: 0px; - font-size: 8px; - top: 1px; - bottom: 1px; - right: 2px; -} - -.OpenIdAjaxTextBox .yui-split-button span button -{ - font-size: 50%; - font-size: 60%\9; /* the \9 is a hack that causes only IE7/8 to use this value. */ - line-height: 1; - min-height: 1em; - padding-top: 2px; - padding-top: 3px\9; - padding-bottom: 1px; - padding-left: 5px; - height: auto; -} - -.OpenIdAjaxTextBox .yuimenuitem .yuimenuitemlabel -{ - padding-left: 5px; -} - -.OpenIdAjaxTextBox .yuimenuitem .yuimenuitemlabel img -{ - border: 0; - margin-right: 4px; - vertical-align: middle; - width: 16px; - height: 16px; -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdAjaxTextBox.js b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdAjaxTextBox.js deleted file mode 100644 index 9907b4e..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdAjaxTextBox.js +++ /dev/null @@ -1,644 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdAjaxTextBox.js" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// This file may be used and redistributed under the terms of the -// Microsoft Public License (Ms-PL) http://opensource.org/licenses/ms-pl.html -// </copyright> -//----------------------------------------------------------------------- - -function initAjaxOpenId(box, openid_logo_url, spinner_url, success_icon_url, failure_icon_url, - throttle, timeout, assertionReceivedCode, - loginButtonText, loginButtonToolTip, showLoginPostBackButton, loginPostBackToolTip, - retryButtonText, retryButtonToolTip, busyToolTip, - identifierRequiredMessage, loginInProgressMessage, - authenticatedByToolTip, authenticatedAsToolTip, authenticationFailedToolTip, - autoPostback, postback) { - box.dnoi_internal = { - postback: postback - }; - if (assertionReceivedCode) { - box.dnoi_internal.onauthenticated = function(sender, e) { eval(assertionReceivedCode); }; - } - - box.dnoi_internal.originalBackground = box.style.background; - box.timeout = timeout; - - box.dnoi_internal.authenticationIFrames = new window.dnoa_internal.FrameManager(throttle); - - box.dnoi_internal.constructButton = function(text, tooltip, onclick) { - var button = document.createElement('input'); - button.textContent = text; // Mozilla - button.value = text; // IE - button.type = 'button'; - button.title = tooltip || ''; - button.onclick = onclick; - box.parentNode.appendChild(button); - return button; - }; - - box.dnoi_internal.constructSplitButton = function(text, tooltip, onclick, menu) { - var htmlButton = box.dnoi_internal.constructButton(text, tooltip, onclick); - - if (!box.parentNode.className || box.parentNode.className.indexOf(' yui-skin-sam') < 0) { - box.parentNode.className = (box.parentNode.className || '') + ' yui-skin-sam'; - } - - var splitButton = new YAHOO.widget.Button(htmlButton, { - type: 'split', - menu: menu - }); - - splitButton.on('click', onclick); - - return splitButton; - }; - - box.dnoi_internal.createLoginPostBackButton = function() { - var postback = function() { - var discoveryResult = window.dnoa_internal.discoveryResults[box.value]; - var respondingEndpoint = discoveryResult.findSuccessfulRequest(); - box.dnoi_internal.postback(discoveryResult, respondingEndpoint, respondingEndpoint.extensionResponses, { background: false }); - }; - var button = box.dnoi_internal.constructButton(loginButtonText, loginPostBackToolTip, postback); - button.style.visibility = 'visible'; - button.destroy = function() { - button.parentNode.removeChild(button); - }; - - return button; - }; - - box.dnoi_internal.createLoginButton = function(providers) { - var onMenuItemClick = function(p_sType, p_aArgs, p_oItem) { - var selectedProvider = (p_oItem && p_oItem.value) ? p_oItem.value : providers[0].value; - selectedProvider.loginPopup(); - return false; - }; - - for (var i = 0; i < providers.length; i++) { - providers[i].onclick = { fn: onMenuItemClick }; - } - - // We'll use the split button if we have more than one Provider, and the YUI library is available. - if (providers.length > 1 && YAHOO && YAHOO.widget && YAHOO.widget.Button) { - return box.dnoi_internal.constructSplitButton(loginButtonText, loginButtonToolTip, onMenuItemClick, providers); - } else { - var button = box.dnoi_internal.constructButton(loginButtonText, loginButtonToolTip, onMenuItemClick); - button.style.visibility = 'visible'; - button.destroy = function() { - button.parentNode.removeChild(button); - }; - return button; - } - }; - - box.dnoi_internal.constructIcon = function(imageUrl, tooltip, rightSide, visible, height) { - var icon = document.createElement('img'); - icon.src = imageUrl; - icon.title = tooltip || ''; - icon.originalTitle = icon.title; - if (!visible) { - icon.style.visibility = 'hidden'; - } - icon.style.position = 'absolute'; - icon.style.top = "2px"; - icon.style.bottom = "2px"; // for FireFox (and IE7, I think) - if (height) { - icon.style.height = height; // for Chrome and IE8 - } - if (rightSide) { - icon.style.right = "2px"; - } else { - icon.style.left = "2px"; - } - box.parentNode.appendChild(icon); - return icon; - }; - - box.dnoi_internal.prefetchImage = function(imageUrl) { - var img = document.createElement('img'); - img.src = imageUrl; - img.style.display = 'none'; - box.parentNode.appendChild(img); - return img; - }; - - function findParentForm(element) { - if (!element || element.nodeName == "FORM") { - return element; - } - - return findParentForm(element.parentNode); - } - - box.parentForm = findParentForm(box); - - function findOrCreateHiddenField() { - var name = box.name + '_openidAuthData'; - var existing = window.document.getElementsByName(name); - if (existing && existing.length > 0) { - return existing[0]; - } - - var hiddenField = document.createElement('input'); - hiddenField.setAttribute("name", name); - hiddenField.setAttribute("type", "hidden"); - box.parentForm.appendChild(hiddenField); - return hiddenField; - } - - box.dnoi_internal.retryButton = box.dnoi_internal.constructButton(retryButtonText, retryButtonToolTip, function() { - box.timeout += 5000; // give the retry attempt 5s longer than the last attempt - box.dnoi_internal.performDiscovery(); - return false; - }); - box.dnoi_internal.openid_logo = box.dnoi_internal.constructIcon(openid_logo_url, null, false, true); - box.dnoi_internal.op_logo = box.dnoi_internal.constructIcon('', authenticatedByToolTip, false, false, "16px"); - box.dnoi_internal.op_logo.style.maxWidth = '16px'; - box.dnoi_internal.spinner = box.dnoi_internal.constructIcon(spinner_url, busyToolTip, true); - box.dnoi_internal.success_icon = box.dnoi_internal.constructIcon(success_icon_url, authenticatedAsToolTip, true); - box.dnoi_internal.failure_icon = box.dnoi_internal.constructIcon(failure_icon_url, authenticationFailedToolTip, true); - - box.dnoi_internal.dnoi_logo = box.dnoi_internal.openid_logo; - - box.dnoi_internal.setVisualCue = function(state, authenticatedBy, authenticatedAs, providers, errorMessage) { - box.dnoi_internal.openid_logo.style.visibility = 'hidden'; - box.dnoi_internal.dnoi_logo.style.visibility = 'hidden'; - box.dnoi_internal.op_logo.style.visibility = 'hidden'; - box.dnoi_internal.openid_logo.title = box.dnoi_internal.openid_logo.originalTitle; - box.dnoi_internal.spinner.style.visibility = 'hidden'; - box.dnoi_internal.success_icon.style.visibility = 'hidden'; - box.dnoi_internal.failure_icon.style.visibility = 'hidden'; - box.dnoi_internal.retryButton.style.visibility = 'hidden'; - if (box.dnoi_internal.loginButton) { - box.dnoi_internal.loginButton.destroy(); - box.dnoi_internal.loginButton = null; - } - if (box.dnoi_internal.postbackLoginButton) { - box.dnoi_internal.postbackLoginButton.destroy(); - box.dnoi_internal.postbackLoginButton = null; - } - box.title = ''; - box.dnoi_internal.state = state; - var opLogo; - if (state == "discovering") { - box.dnoi_internal.dnoi_logo.style.visibility = 'visible'; - box.dnoi_internal.spinner.style.visibility = 'visible'; - box.dnoi_internal.claimedIdentifier = null; - box.title = ''; - window.status = "Discovering OpenID Identifier '" + box.value + "'..."; - } else if (state == "authenticated") { - opLogo = box.dnoi_internal.deriveOPFavIcon(); - if (opLogo) { - box.dnoi_internal.op_logo.src = opLogo; - box.dnoi_internal.op_logo.style.visibility = 'visible'; - box.dnoi_internal.op_logo.title = box.dnoi_internal.op_logo.originalTitle.replace('{0}', authenticatedBy.getHost()); - } - //trace("OP icon size: " + box.dnoi_internal.op_logo.fileSize); - // The filesize check just doesn't seem to work any more. - if (!opLogo) {// || box.dnoi_internal.op_logo.fileSize == -1 /*IE*/ || box.dnoi_internal.op_logo.fileSize === undefined /* FF */) { - trace('recovering from missing OP icon'); - box.dnoi_internal.op_logo.style.visibility = 'hidden'; - box.dnoi_internal.openid_logo.style.visibility = 'visible'; - box.dnoi_internal.openid_logo.title = box.dnoi_internal.op_logo.originalTitle.replace('{0}', authenticatedBy.getHost()); - } - if (showLoginPostBackButton) { - box.dnoi_internal.postbackLoginButton = box.dnoi_internal.createLoginPostBackButton(); - } else { - box.dnoi_internal.success_icon.style.visibility = 'visible'; - box.dnoi_internal.success_icon.title = box.dnoi_internal.success_icon.originalTitle.replace('{0}', authenticatedAs); - } - box.title = box.dnoi_internal.claimedIdentifier; - window.status = "Authenticated as " + authenticatedAs; - } else if (state == "setup") { - opLogo = box.dnoi_internal.deriveOPFavIcon(); - if (opLogo) { - box.dnoi_internal.op_logo.src = opLogo; - box.dnoi_internal.op_logo.style.visibility = 'visible'; - } else { - box.dnoi_internal.openid_logo.style.visibility = 'visible'; - } - - box.dnoi_internal.loginButton = box.dnoi_internal.createLoginButton(providers); - - box.dnoi_internal.claimedIdentifier = null; - window.status = "Authentication requires user interaction."; - } else if (state == "failed") { - box.dnoi_internal.openid_logo.style.visibility = 'visible'; - box.dnoi_internal.retryButton.style.visibility = 'visible'; - box.dnoi_internal.claimedIdentifier = null; - window.status = authenticationFailedToolTip; - box.title = authenticationFailedToolTip; - } else if (state == "failednoretry") { - box.dnoi_internal.failure_icon.title = errorMessage; - box.dnoi_internal.failure_icon.style.visibility = 'visible'; - box.dnoi_internal.openid_logo.style.visibility = 'visible'; - box.dnoi_internal.claimedIdentifier = null; - window.status = errorMessage; - box.title = errorMessage; - } else if (state == '' || !state) { - box.dnoi_internal.openid_logo.style.visibility = 'visible'; - box.title = ''; - box.dnoi_internal.claimedIdentifier = null; - window.status = null; - } else { - box.dnoi_internal.claimedIdentifier = null; - trace('unrecognized state ' + state); - } - - if (box.onStateChanged) { - box.onStateChanged(state); - } - }; - - box.dnoi_internal.isBusy = function() { - var lastDiscovery = window.dnoa_internal.discoveryResults[box.lastDiscoveredIdentifier]; - return box.dnoi_internal.state == 'discovering' || - (lastDiscovery && lastDiscovery.busy()); - }; - - box.dnoi_internal.canAttemptLogin = function() { - if (box.value.length === 0) { return false; } - if (!window.dnoa_internal.discoveryResults[box.value]) { return false; } - if (box.dnoi_internal.state == 'failed') { return false; } - return true; - }; - - box.dnoi_internal.getUserSuppliedIdentifierResults = function() { - return window.dnoa_internal.discoveryResults[box.value]; - }; - - box.dnoi_internal.isAuthenticated = function() { - var results = box.dnoi_internal.getUserSuppliedIdentifierResults(); - return results && results.findSuccessfulRequest(); - }; - - box.dnoi_internal.onSubmit = function() { - var hiddenField = findOrCreateHiddenField(); - if (box.dnoi_internal.isAuthenticated()) { - // stick the result in a hidden field so the RP can verify it - hiddenField.setAttribute("value", window.dnoa_internal.discoveryResults[box.value].successAuthData); - } else { - hiddenField.setAttribute("value", ''); - if (box.dnoi_internal.isBusy()) { - alert(loginInProgressMessage); - } else { - if (box.value.length > 0) { - // submitPending will be true if we've already tried deferring submit for a login, - // in which case we just want to display a box to the user. - if (box.dnoi_internal.submitPending || !box.dnoi_internal.canAttemptLogin()) { - alert(identifierRequiredMessage); - } else { - // The user hasn't clicked "Login" yet. We'll click login for him, - // after leaving a note for ourselves to automatically click submit - // when login is complete. - box.dnoi_internal.submitPending = box.dnoi_internal.submitButtonJustClicked; - if (box.dnoi_internal.submitPending === null) { - box.dnoi_internal.submitPending = true; - } - box.dnoi_internal.loginButton.onclick(); - return false; // abort submit for now - } - } else { - return true; - } - } - return false; - } - return true; - }; - - /// <summary> - /// Records which submit button caused this openid box to question whether it - /// was ready to submit the user's identifier so that that button can be re-invoked - /// automatically after authentication completes. - /// </summary> - box.dnoi_internal.setLastSubmitButtonClicked = function(evt) { - var button; - if (evt.target) { - button = evt.target; - } else { - button = evt.srcElement; - } - - box.dnoi_internal.submitButtonJustClicked = button; - }; - - // Find all submit buttons and hook their click events so that we can validate - // whether we are ready for the user to postback. - var inputs = document.getElementsByTagName('input'); - for (var i = 0; i < inputs.length; i++) { - var el = inputs[i]; - if (el.type == 'submit') { - if (el.attachEvent) { - el.attachEvent("onclick", box.dnoi_internal.setLastSubmitButtonClicked); - } else { - el.addEventListener("click", box.dnoi_internal.setLastSubmitButtonClicked, true); - } - } - } - - /// <summary> - /// Returns the URL of the authenticating OP's logo so it can be displayed to the user. - /// </summary> - /// <param name="opUri">The OP Endpoint, if known.</param> - box.dnoi_internal.deriveOPFavIcon = function(opUri) { - if (!opUri) { - var idresults = box.dnoi_internal.getUserSuppliedIdentifierResults(); - var response = idresults ? idresults.successAuthData : null; - if (!response || response.length === 0) { - trace('No favicon because no successAuthData.'); - return; - } - var authResult = new window.dnoa_internal.Uri(response); - if (authResult.getQueryArgValue("openid.op_endpoint")) { - opUri = new window.dnoa_internal.Uri(authResult.getQueryArgValue("openid.op_endpoint")); - } else if (authResult.getQueryArgValue("dnoa.op_endpoint")) { - opUri = new window.dnoa_internal.Uri(authResult.getQueryArgValue("dnoa.op_endpoint")); - } else if (authResult.getQueryArgValue("openid.user_setup_url")) { - opUri = new window.dnoa_internal.Uri(authResult.getQueryArgValue("openid.user_setup_url")); - } else { - return null; - } - } - var favicon = opUri.getAuthority() + "/favicon.ico"; - trace('Guessing favicon location of: ' + favicon); - return favicon; - }; - - /***************************************** - * Event Handlers - *****************************************/ - - window.dnoa_internal.addDiscoveryStarted(function(identifier) { - if (identifier == box.value) { - box.dnoi_internal.setVisualCue('discovering'); - } - }, box); - - window.dnoa_internal.addDiscoverySuccess(function(identifier, discoveryResult, state) { - if (identifier == box.value && (box.dnoi_internal.state == 'discovering' || !box.dnoi_internal.state)) { - // Start pre-fetching the OP favicons - for (var i = 0; i < discoveryResult.length; i++) { - var favicon = box.dnoi_internal.deriveOPFavIcon(discoveryResult[i].endpoint); - if (favicon) { - trace('Prefetching ' + favicon); - box.dnoi_internal.prefetchImage(favicon); - } - } - if (discoveryResult.length > 0) { - discoveryResult.loginBackground( - box.dnoi_internal.authenticationIFrames, - null, - null, - null, - box.timeout); - } else { - // discovery completed successfully -- it just didn't yield any service endpoints. - box.dnoi_internal.setVisualCue('failednoretry', null, null, null, discoveryResult.error); - if (discoveryResult.error) { box.title = discoveryResult.error; } - } - } - }, box); - - window.dnoa_internal.addDiscoveryFailed(function(identifier, message) { - if (identifier == box.value) { - box.dnoi_internal.setVisualCue('failed'); - if (message) { box.title = message; } - } - }, box); - - window.dnoa_internal.addAuthStarted(function(discoveryResult, serviceEndpoint, state) { - if (discoveryResult.userSuppliedIdentifier == box.value) { - box.dnoi_internal.setVisualCue('discovering'); - } - }, box); - - window.dnoa_internal.addAuthSuccess(function(discoveryResult, serviceEndpoint, extensionResponses, state) { - if (discoveryResult.userSuppliedIdentifier == box.value) { - // visual cue that auth was successful - var parsedPositiveAssertion = new window.dnoa_internal.PositiveAssertion(discoveryResult.successAuthData); - box.dnoi_internal.claimedIdentifier = parsedPositiveAssertion.claimedIdentifier; - - // If the OP doesn't support delegation, "correct" the identifier the user entered - // so he realizes his identity didn't stick. But don't change out OP Identifiers. - if (discoveryResult.claimedIdentifier && discoveryResult.claimedIdentifier != parsedPositiveAssertion.claimedIdentifier) { - box.value = parsedPositiveAssertion.claimedIdentifier; - box.lastDiscoveredIdentifier = box.value; - - // Also inject a fake discovery result for this new identifier to keep the UI from performing - // discovery on the new identifier (the RP will perform the necessary verification server-side). - if (!window.dnoa_internal.discoveryResults[box.value]) { - // We must make sure that the only service endpoint from the earlier discovery that - // is copied over is the one that sent the assertion just now. Deep clone, then strip - // out the other SEPs. - window.dnoa_internal.discoveryResults[box.value] = discoveryResult.cloneWithOneServiceEndpoint(serviceEndpoint); - } - } - box.dnoi_internal.setVisualCue('authenticated', parsedPositiveAssertion.endpoint, parsedPositiveAssertion.claimedIdentifier); - if (box.dnoi_internal.onauthenticated) { - box.dnoi_internal.onauthenticated(box, extensionResponses); - } - - if (showLoginPostBackButton && !state.background) { - box.dnoi_internal.postback(discoveryResult, serviceEndpoint, extensionResponses, state); - } else if (box.dnoi_internal.submitPending) { - // We submit the form BEFORE resetting the submitPending so - // the submit handler knows we've already tried this route. - if (box.dnoi_internal.submitPending === true) { - box.parentForm.submit(); - } else { - box.dnoi_internal.submitPending.click(); - } - - box.dnoi_internal.submitPending = null; - } else if (!state.deserialized && autoPostback) { - // as long as this is a fresh auth response, postback to the server if configured to do so. - box.dnoi_internal.postback(discoveryResult, serviceEndpoint, extensionResponses, state); - } - } - }, box); - - window.dnoa_internal.addAuthFailed(function(discoveryResult, serviceEndpoint, state) { - if (discoveryResult.userSuppliedIdentifier == box.value) { - box.dnoi_internal.submitPending = null; - if (!serviceEndpoint || !state.background) { // if the last service endpoint just turned the user down - box.dnoi_internal.displayLoginButton(discoveryResult); - } - } - }, box); - - window.dnoa_internal.addAuthCleared(function(discoveryResult, serviceEndpoint) { - if (discoveryResult.userSuppliedIdentifier == box.value) { - if (!discoveryResult.findSuccessfulRequest()) { - // attempt to renew the positive assertion. - discoveryResult.loginBackground( - box.dnoi_internal.authenticationIFrames, - null, - null, - null, - box.timeout); - } - } - }, box); - - /***************************************** - * Flow - *****************************************/ - - box.dnoi_internal.displayLoginButton = function(discoveryResult) { - trace('No asynchronous authentication attempt is in progress. Display setup view.'); - var providers = []; - for (var i = 0; i < discoveryResult.length; i++) { - var favicon = box.dnoi_internal.deriveOPFavIcon(discoveryResult[i].endpoint); - var img = '<img src="' + favicon + '" />'; - providers.push({ text: img + discoveryResult[i].host, value: discoveryResult[i] }); - } - - // visual cue that auth failed - box.dnoi_internal.setVisualCue('setup', null, null, providers); - }; - - /// <summary>Called to initiate discovery on some identifier.</summary> - box.dnoi_internal.performDiscovery = function() { - box.dnoi_internal.authenticationIFrames.closeFrames(); - box.lastDiscoveredIdentifier = box.value; - var openid = new window.OpenIdIdentifier(box.value); - openid.discover(); - }; - - box.onblur = function(event) { - if (box.lastDiscoveredIdentifier != box.value || !box.dnoi_internal.state) { - if (box.value.length > 0) { - box.dnoi_internal.resetAndDiscover(); - } else { - box.dnoi_internal.setVisualCue(); - } - } - - return true; - }; - - //{ - var rate = NaN; - var lastValue = box.value; - var keyPresses = 0; - var startTime = null; - var lastKeyPress = null; - var discoveryTimer; - - function cancelTimer() { - if (discoveryTimer) { - trace('canceling timer', 'gray'); - clearTimeout(discoveryTimer); - discoveryTimer = null; - } - } - - function identifierSanityCheck(id) { - return id.match("^[=@+$!(].+|.*?\\..*[^\\.]|\\w+://.+"); - } - - function discover() { - cancelTimer(); - trace('typist discovery candidate', 'gray'); - if (identifierSanityCheck(box.value)) { - trace('typist discovery begun', 'gray'); - box.dnoi_internal.performDiscovery(); - } else { - trace('typist discovery canceled due to incomplete identifier.', 'gray'); - } - } - - function reset() { - keyPresses = 0; - startTime = null; - rate = NaN; - trace('resetting state', 'gray'); - } - - box.dnoi_internal.resetAndDiscover = function() { - reset(); - discover(); - }; - - box.onkeyup = function(e) { - e = e || window.event; // for IE - - if (new Date() - lastKeyPress > 3000) { - // the user seems to have altogether stopped typing, - // so reset our typist speed detector. - reset(); - } - lastKeyPress = new Date(); - - var newValue = box.value; - if (e.keyCode == 13) { - if (box.dnoi_internal.state === 'setup') { - box.dnoi_internal.loginButton.click(); - } else if (box.dnoi_internal.postbackLoginButton) { - box.dnoi_internal.postbackLoginButton.click(); - } else { - discover(); - } - } else { - if (lastValue != newValue && newValue != box.lastDiscoveredIdentifier) { - box.dnoi_internal.setVisualCue(); - if (newValue.length === 0) { - reset(); - } else if (Math.abs((lastValue || '').length - newValue.length) > 1) { - // One key press is responsible for multiple character changes. - // The user may have pasted in his identifier in which case - // we want to begin discovery immediately. - trace(newValue + ': paste detected (old value ' + lastValue + ')', 'gray'); - discover(); - } else { - keyPresses++; - var timeout = 3000; // timeout to use if we don't have enough keying to figure out type rate - if (startTime === null) { - startTime = new Date(); - } else if (keyPresses > 1) { - cancelTimer(); - rate = (new Date() - startTime) / keyPresses; - var minTimeout = 300; - var maxTimeout = 3000; - var typistFactor = 5; - timeout = Math.max(minTimeout, Math.min(rate * typistFactor, maxTimeout)); - } - - trace(newValue + ': setting timer for ' + timeout, 'gray'); - discoveryTimer = setTimeout(discover, timeout); - } - } - } - - trace(newValue + ': updating lastValue', 'gray'); - lastValue = newValue; - - return true; - }; - //} - - box.getClaimedIdentifier = function() { return box.dnoi_internal.claimedIdentifier; }; - - // If an identifier is preset on the box, perform discovery on it, but only - // if there isn't a prior authentication that we're about to deserialize. - if (box.value.length > 0 && findOrCreateHiddenField().value.length === 0) { - trace('jumpstarting discovery on ' + box.value + ' because it was preset.'); - box.dnoi_internal.performDiscovery(); - } - - // Restore a previously achieved state (from pre-postback) if it is given. - window.dnoa_internal.deserializePreviousAuthentication(findOrCreateHiddenField().value); - - // public methods - box.setValue = function(value) { - box.value = value; - if (box.value) { - box.dnoi_internal.performDiscovery(); - } - }; - - // public events - // box.onStateChanged(state) -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdButton.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdButton.cs deleted file mode 100644 index 6243917..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdButton.cs +++ /dev/null @@ -1,179 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdButton.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OpenId.RelyingParty { - using System; - using System.Collections.Generic; - using System.ComponentModel; - using System.Diagnostics.CodeAnalysis; - using System.Drawing.Design; - using System.Globalization; - using System.Linq; - using System.Text; - using System.Web.UI; - using DotNetOpenAuth.Messaging; - - /// <summary> - /// An ASP.NET control that renders a button that initiates an - /// authentication when clicked. - /// </summary> - public class OpenIdButton : OpenIdRelyingPartyControlBase { - #region Property defaults - - /// <summary> - /// The default value for the <see cref="Text"/> property. - /// </summary> - private const string TextDefault = "Log in with [Provider]!"; - - /// <summary> - /// The default value for the <see cref="PrecreateRequest"/> property. - /// </summary> - private const bool PrecreateRequestDefault = false; - - #endregion - - #region View state keys - - /// <summary> - /// The key under which the value for the <see cref="Text"/> property will be stored. - /// </summary> - private const string TextViewStateKey = "Text"; - - /// <summary> - /// The key under which the value for the <see cref="ImageUrl"/> property will be stored. - /// </summary> - private const string ImageUrlViewStateKey = "ImageUrl"; - - /// <summary> - /// The key under which the value for the <see cref="PrecreateRequest"/> property will be stored. - /// </summary> - private const string PrecreateRequestViewStateKey = "PrecreateRequest"; - - #endregion - - /// <summary> - /// Initializes a new instance of the <see cref="OpenIdButton"/> class. - /// </summary> - public OpenIdButton() { - } - - /// <summary> - /// Gets or sets the text to display for the link. - /// </summary> - [Bindable(true), DefaultValue(TextDefault), Category(AppearanceCategory)] - [Description("The text to display for the link.")] - public string Text { - get { return (string)ViewState[TextViewStateKey] ?? TextDefault; } - set { ViewState[TextViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the image to display. - /// </summary> - [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Bindable property must be simple type")] - [Bindable(true), Category(AppearanceCategory)] - [Description("The image to display.")] - [UrlProperty, Editor("System.Web.UI.Design.UrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))] - public string ImageUrl { - get { - return (string)ViewState[ImageUrlViewStateKey]; - } - - set { - UriUtil.ValidateResolvableUrl(Page, DesignMode, value); - ViewState[ImageUrlViewStateKey] = value; - } - } - - /// <summary> - /// Gets or sets a value indicating whether to pre-discover the identifier so - /// the user agent has an immediate redirect. - /// </summary> - [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Precreate", Justification = "Breaking change to public API")] - [Bindable(true), Category(OpenIdCategory), DefaultValue(PrecreateRequestDefault)] - [Description("Whether to pre-discover the identifier so the user agent has an immediate redirect.")] - public bool PrecreateRequest { - get { return (bool)(ViewState[PrecreateRequestViewStateKey] ?? PrecreateRequestDefault); } - set { ViewState[PrecreateRequestViewStateKey] = value; } - } - - /// <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(false), Browsable(false)] - public override PopupBehavior Popup { - get { return base.Popup; } - set { ErrorUtilities.VerifySupported(value == base.Popup, OpenIdStrings.PropertyValueNotSupported); } - } - - /// <summary> - /// When implemented by a class, enables a server control to process an event raised when a form is posted to the server. - /// </summary> - /// <param name="eventArgument">A <see cref="T:System.String"/> that represents an optional event argument to be passed to the event handler.</param> - protected override void RaisePostBackEvent(string eventArgument) { - if (!this.PrecreateRequest) { - try { - IAuthenticationRequest request = this.CreateRequests().First(); - request.RedirectToProvider(); - } catch (InvalidOperationException ex) { - throw ErrorUtilities.Wrap(ex, OpenIdStrings.OpenIdEndpointNotFound); - } - } - } - - /// <summary> - /// Raises the <see cref="E:System.Web.UI.Control.PreRender"/> event. - /// </summary> - /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param> - protected override void OnPreRender(EventArgs e) { - base.OnPreRender(e); - - if (!this.DesignMode) { - ErrorUtilities.VerifyOperation(this.Identifier != null, OpenIdStrings.NoIdentifierSet); - } - } - - /// <summary> - /// Sends server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object, which writes the content to be rendered on the client. - /// </summary> - /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param> - [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.HtmlTextWriter.WriteEncodedText(System.String)", Justification = "Not localizable")] - protected override void Render(HtmlTextWriter writer) { - if (string.IsNullOrEmpty(this.Identifier)) { - writer.WriteEncodedText(string.Format(CultureInfo.CurrentCulture, "[{0}]", OpenIdStrings.NoIdentifierSet)); - } else { - string tooltip = this.Text; - if (this.PrecreateRequest && !this.DesignMode) { - IAuthenticationRequest request = this.CreateRequests().FirstOrDefault(); - if (request != null) { - RenderOpenIdMessageTransmissionAsAnchorAttributes(writer, request, tooltip); - } else { - tooltip = OpenIdStrings.OpenIdEndpointNotFound; - } - } else { - writer.AddAttribute(HtmlTextWriterAttribute.Href, this.Page.ClientScript.GetPostBackClientHyperlink(this, null)); - } - - writer.AddAttribute(HtmlTextWriterAttribute.Title, tooltip); - writer.RenderBeginTag(HtmlTextWriterTag.A); - - if (!string.IsNullOrEmpty(this.ImageUrl)) { - writer.AddAttribute(HtmlTextWriterAttribute.Src, this.ResolveClientUrl(this.ImageUrl)); - writer.AddAttribute(HtmlTextWriterAttribute.Border, "0"); - writer.AddAttribute(HtmlTextWriterAttribute.Alt, this.Text); - writer.AddAttribute(HtmlTextWriterAttribute.Title, this.Text); - writer.RenderBeginTag(HtmlTextWriterTag.Img); - writer.RenderEndTag(); - } else if (!string.IsNullOrEmpty(this.Text)) { - writer.WriteEncodedText(this.Text); - } - - writer.RenderEndTag(); - } - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdEventArgs.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdEventArgs.cs deleted file mode 100644 index 5668cf4..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdEventArgs.cs +++ /dev/null @@ -1,74 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdEventArgs.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OpenId.RelyingParty { - using System; - using System.Collections.Generic; - using System.Diagnostics.Contracts; - using System.Linq; - using System.Text; - using DotNetOpenAuth.Messaging; - - /// <summary> - /// The event details passed to event handlers. - /// </summary> - public class OpenIdEventArgs : EventArgs { - /// <summary> - /// Initializes a new instance of the <see cref="OpenIdEventArgs"/> class - /// with minimal information of an incomplete or failed authentication attempt. - /// </summary> - /// <param name="request">The outgoing authentication request.</param> - internal OpenIdEventArgs(IAuthenticationRequest request) { - Contract.Requires<ArgumentNullException>(request != null); - - this.Request = request; - this.ClaimedIdentifier = request.ClaimedIdentifier; - this.IsDirectedIdentity = request.IsDirectedIdentity; - } - - /// <summary> - /// Initializes a new instance of the <see cref="OpenIdEventArgs"/> class - /// with information on a completed authentication attempt - /// (whether that attempt was successful or not). - /// </summary> - /// <param name="response">The incoming authentication response.</param> - internal OpenIdEventArgs(IAuthenticationResponse response) { - Contract.Requires<ArgumentNullException>(response != null); - - this.Response = response; - this.ClaimedIdentifier = response.ClaimedIdentifier; - } - - /// <summary> - /// Gets or sets a value indicating whether to cancel - /// the OpenID authentication and/or login process. - /// </summary> - public bool Cancel { get; set; } - - /// <summary> - /// Gets the Identifier the user is claiming to own. Or null if the user - /// is using Directed Identity. - /// </summary> - public Identifier ClaimedIdentifier { get; private set; } - - /// <summary> - /// Gets a value indicating whether the user has selected to let his Provider determine - /// the ClaimedIdentifier to use as part of successful authentication. - /// </summary> - public bool IsDirectedIdentity { get; private set; } - - /// <summary> - /// Gets the details of the OpenID authentication request, - /// and allows for adding extensions. - /// </summary> - public IAuthenticationRequest Request { get; private set; } - - /// <summary> - /// Gets the details of the OpenID authentication response. - /// </summary> - public IAuthenticationResponse Response { get; private set; } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdLogin.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdLogin.cs deleted file mode 100644 index eccdacf..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdLogin.cs +++ /dev/null @@ -1,1001 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdLogin.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OpenId.RelyingParty { - using System; - using System.ComponentModel; - using System.Diagnostics.CodeAnalysis; - using System.Diagnostics.Contracts; - using System.Globalization; - using System.Linq; - using System.Web.UI; - using System.Web.UI.HtmlControls; - using System.Web.UI.WebControls; - using DotNetOpenAuth.Messaging; - - /// <summary> - /// An ASP.NET control providing a complete OpenID login experience. - /// </summary> - [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Login", Justification = "Legacy code")] - [DefaultProperty("Text"), ValidationProperty("Text")] - [ToolboxData("<{0}:OpenIdLogin runat=\"server\" />")] - public class OpenIdLogin : OpenIdTextBox { - #region Property defaults - - /// <summary> - /// The default value for the <see cref="RegisterToolTip"/> property. - /// </summary> - private const string RegisterToolTipDefault = "Sign up free for an OpenID with MyOpenID now."; - - /// <summary> - /// The default value for the <see cref="RememberMeText"/> property. - /// </summary> - private const string RememberMeTextDefault = "Remember me"; - - /// <summary> - /// The default value for the <see cref="ButtonText"/> property. - /// </summary> - private const string ButtonTextDefault = "Login »"; - - /// <summary> - /// The default value for the <see cref="CanceledText"/> property. - /// </summary> - private const string CanceledTextDefault = "Login canceled."; - - /// <summary> - /// The default value for the <see cref="FailedMessageText"/> property. - /// </summary> - private const string FailedMessageTextDefault = "Login failed: {0}"; - - /// <summary> - /// The default value for the <see cref="ExamplePrefix"/> property. - /// </summary> - private const string ExamplePrefixDefault = "Example:"; - - /// <summary> - /// The default value for the <see cref="ExampleUrl"/> property. - /// </summary> - private const string ExampleUrlDefault = "http://your.name.myopenid.com"; - - /// <summary> - /// The default value for the <see cref="LabelText"/> property. - /// </summary> - private const string LabelTextDefault = "OpenID Login:"; - - /// <summary> - /// The default value for the <see cref="RequiredText"/> property. - /// </summary> - private const string RequiredTextDefault = "Provide an OpenID first."; - - /// <summary> - /// The default value for the <see cref="UriFormatText"/> property. - /// </summary> - private const string UriFormatTextDefault = "Invalid OpenID URL."; - - /// <summary> - /// The default value for the <see cref="RegisterText"/> property. - /// </summary> - private const string RegisterTextDefault = "register"; - - /// <summary> - /// The default value for the <see cref="RegisterUrl"/> property. - /// </summary> - private const string RegisterUrlDefault = "https://www.myopenid.com/signup"; - - /// <summary> - /// The default value for the <see cref="ButtonToolTip"/> property. - /// </summary> - private const string ButtonToolTipDefault = "Account login"; - - /// <summary> - /// The default value for the <see cref="ValidationGroup"/> property. - /// </summary> - private const string ValidationGroupDefault = "OpenIdLogin"; - - /// <summary> - /// The default value for the <see cref="RegisterVisible"/> property. - /// </summary> - private const bool RegisterVisibleDefault = true; - - /// <summary> - /// The default value for the <see cref="RememberMeVisible"/> property. - /// </summary> - private const bool RememberMeVisibleDefault = false; - - /// <summary> - /// The default value for the <see cref="RememberMe"/> property. - /// </summary> - private const bool RememberMeDefault = false; - - /// <summary> - /// The default value for the <see cref="UriValidatorEnabled"/> property. - /// </summary> - private const bool UriValidatorEnabledDefault = true; - - #endregion - - #region Property viewstate keys - - /// <summary> - /// The viewstate key to use for the <see cref="FailedMessageText"/> property. - /// </summary> - private const string FailedMessageTextViewStateKey = "FailedMessageText"; - - /// <summary> - /// The viewstate key to use for the <see cref="CanceledText"/> property. - /// </summary> - private const string CanceledTextViewStateKey = "CanceledText"; - - /// <summary> - /// The viewstate key to use for the <see cref="IdSelectorIdentifier"/> property. - /// </summary> - private const string IdSelectorIdentifierViewStateKey = "IdSelectorIdentifier"; - - #endregion - - /// <summary> - /// The HTML to append to the <see cref="RequiredText"/> property value when rendering. - /// </summary> - private const string RequiredTextSuffix = "<br/>"; - - /// <summary> - /// The number to add to <see cref="TabIndex"/> to get the tab index of the textbox control. - /// </summary> - private const short TextBoxTabIndexOffset = 0; - - /// <summary> - /// The number to add to <see cref="TabIndex"/> to get the tab index of the login button control. - /// </summary> - private const short LoginButtonTabIndexOffset = 1; - - /// <summary> - /// The number to add to <see cref="TabIndex"/> to get the tab index of the remember me checkbox control. - /// </summary> - private const short RememberMeTabIndexOffset = 2; - - /// <summary> - /// The number to add to <see cref="TabIndex"/> to get the tab index of the register link control. - /// </summary> - private const short RegisterTabIndexOffset = 3; - - #region Controls - - /// <summary> - /// The control into which all other controls are added. - /// </summary> - private Panel panel; - - /// <summary> - /// The Login button. - /// </summary> - private Button loginButton; - - /// <summary> - /// The label that presents the text box. - /// </summary> - private HtmlGenericControl label; - - /// <summary> - /// The validator that flags an empty text box. - /// </summary> - private RequiredFieldValidator requiredValidator; - - /// <summary> - /// The validator that flags invalid formats of OpenID identifiers. - /// </summary> - private CustomValidator identifierFormatValidator; - - /// <summary> - /// The label that precedes an example OpenID identifier. - /// </summary> - private Label examplePrefixLabel; - - /// <summary> - /// The label that contains the example OpenID identifier. - /// </summary> - private Label exampleUrlLabel; - - /// <summary> - /// A link to allow the user to create an account with a popular OpenID Provider. - /// </summary> - private HyperLink registerLink; - - /// <summary> - /// The Remember Me checkbox. - /// </summary> - private CheckBox rememberMeCheckBox; - - /// <summary> - /// The javascript snippet that activates the ID Selector javascript control. - /// </summary> - private Literal idselectorJavascript; - - /// <summary> - /// The label that will display login failure messages. - /// </summary> - private Label errorLabel; - - #endregion - - /// <summary> - /// Initializes a new instance of the <see cref="OpenIdLogin"/> class. - /// </summary> - public OpenIdLogin() { - } - - #region Events - - /// <summary> - /// Fired when the Remember Me checkbox is changed by the user. - /// </summary> - [Description("Fires when the Remember Me checkbox is changed by the user.")] - public event EventHandler RememberMeChanged; - - #endregion - - #region Properties - - /// <summary> - /// Gets a <see cref="T:System.Web.UI.ControlCollection"/> object that represents the child controls for a specified server control in the UI hierarchy. - /// </summary> - /// <returns> - /// The collection of child controls for the specified server control. - /// </returns> - public override ControlCollection Controls { - get { - this.EnsureChildControls(); - return base.Controls; - } - } - - /// <summary> - /// Gets or sets the caption that appears before the text box. - /// </summary> - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(LabelTextDefault)] - [Localizable(true)] - [Description("The caption that appears before the text box.")] - public string LabelText { - get { - EnsureChildControls(); - return this.label.InnerText; - } - - set { - EnsureChildControls(); - this.label.InnerText = value; - } - } - - /// <summary> - /// Gets or sets the text that introduces the example OpenID url. - /// </summary> - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(ExamplePrefixDefault)] - [Localizable(true)] - [Description("The text that introduces the example OpenID url.")] - public string ExamplePrefix { - get { - EnsureChildControls(); - return this.examplePrefixLabel.Text; - } - - set { - EnsureChildControls(); - this.examplePrefixLabel.Text = value; - } - } - - /// <summary> - /// Gets or sets the example OpenID Identifier to display to the user. - /// </summary> - [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Property grid only supports primitive types.")] - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(ExampleUrlDefault)] - [Localizable(true)] - [Description("The example OpenID Identifier to display to the user.")] - public string ExampleUrl { - get { - EnsureChildControls(); - return this.exampleUrlLabel.Text; - } - - set { - EnsureChildControls(); - this.exampleUrlLabel.Text = value; - } - } - - /// <summary> - /// Gets or sets the text to display if the user attempts to login - /// without providing an Identifier. - /// </summary> - [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "br", Justification = "HTML"), Bindable(true)] - [Category("Appearance")] - [DefaultValue(RequiredTextDefault)] - [Localizable(true)] - [Description("The text to display if the user attempts to login without providing an Identifier.")] - public string RequiredText { - get { - EnsureChildControls(); - return this.requiredValidator.Text.Substring(0, this.requiredValidator.Text.Length - RequiredTextSuffix.Length); - } - - set { - EnsureChildControls(); - this.requiredValidator.ErrorMessage = this.requiredValidator.Text = value + RequiredTextSuffix; - } - } - - /// <summary> - /// Gets or sets the text to display if the user provides an invalid form for an Identifier. - /// </summary> - [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "br", Justification = "HTML"), SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Property grid only supports primitive types.")] - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(UriFormatTextDefault)] - [Localizable(true)] - [Description("The text to display if the user provides an invalid form for an Identifier.")] - public string UriFormatText { - get { - EnsureChildControls(); - return this.identifierFormatValidator.Text.Substring(0, this.identifierFormatValidator.Text.Length - RequiredTextSuffix.Length); - } - - set { - EnsureChildControls(); - this.identifierFormatValidator.ErrorMessage = this.identifierFormatValidator.Text = value + RequiredTextSuffix; - } - } - - /// <summary> - /// Gets or sets a value indicating whether to perform Identifier - /// format validation prior to an authentication attempt. - /// </summary> - [Bindable(true)] - [Category("Behavior")] - [DefaultValue(UriValidatorEnabledDefault)] - [Description("Whether to perform Identifier format validation prior to an authentication attempt.")] - public bool UriValidatorEnabled { - get { - EnsureChildControls(); - return this.identifierFormatValidator.Enabled; - } - - set { - EnsureChildControls(); - this.identifierFormatValidator.Enabled = value; - } - } - - /// <summary> - /// Gets or sets the text of the link users can click on to obtain an OpenID. - /// </summary> - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(RegisterTextDefault)] - [Localizable(true)] - [Description("The text of the link users can click on to obtain an OpenID.")] - public string RegisterText { - get { - EnsureChildControls(); - return this.registerLink.Text; - } - - set { - EnsureChildControls(); - this.registerLink.Text = value; - } - } - - /// <summary> - /// Gets or sets the URL to link users to who click the link to obtain a new OpenID. - /// </summary> - [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Property grid only supports primitive types.")] - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(RegisterUrlDefault)] - [Localizable(true)] - [Description("The URL to link users to who click the link to obtain a new OpenID.")] - public string RegisterUrl { - get { - EnsureChildControls(); - return this.registerLink.NavigateUrl; - } - - set { - EnsureChildControls(); - this.registerLink.NavigateUrl = value; - } - } - - /// <summary> - /// Gets or sets the text of the tooltip to display when the user hovers - /// over the link to obtain a new OpenID. - /// </summary> - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(RegisterToolTipDefault)] - [Localizable(true)] - [Description("The text of the tooltip to display when the user hovers over the link to obtain a new OpenID.")] - public string RegisterToolTip { - get { - EnsureChildControls(); - return this.registerLink.ToolTip; - } - - set { - EnsureChildControls(); - this.registerLink.ToolTip = value; - } - } - - /// <summary> - /// Gets or sets a value indicating whether to display a link to - /// allow users to easily obtain a new OpenID. - /// </summary> - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(RegisterVisibleDefault)] - [Description("Whether to display a link to allow users to easily obtain a new OpenID.")] - public bool RegisterVisible { - get { - EnsureChildControls(); - return this.registerLink.Visible; - } - - set { - EnsureChildControls(); - this.registerLink.Visible = value; - } - } - - /// <summary> - /// Gets or sets the text that appears on the button that initiates login. - /// </summary> - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(ButtonTextDefault)] - [Localizable(true)] - [Description("The text that appears on the button that initiates login.")] - public string ButtonText { - get { - EnsureChildControls(); - return this.loginButton.Text; - } - - set { - EnsureChildControls(); - this.loginButton.Text = value; - } - } - - /// <summary> - /// Gets or sets the text of the "Remember Me" checkbox. - /// </summary> - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(RememberMeTextDefault)] - [Localizable(true)] - [Description("The text of the \"Remember Me\" checkbox.")] - public string RememberMeText { - get { - EnsureChildControls(); - return this.rememberMeCheckBox.Text; - } - - set { - EnsureChildControls(); - this.rememberMeCheckBox.Text = value; - } - } - - /// <summary> - /// Gets or sets the message display in the event of a failed - /// authentication. {0} may be used to insert the actual error. - /// </summary> - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(FailedMessageTextDefault)] - [Localizable(true)] - [Description("The message display in the event of a failed authentication. {0} may be used to insert the actual error.")] - public string FailedMessageText { - get { return (string)ViewState[FailedMessageTextViewStateKey] ?? FailedMessageTextDefault; } - set { ViewState[FailedMessageTextViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the text to display in the event of an authentication canceled at the Provider. - /// </summary> - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(CanceledTextDefault)] - [Localizable(true)] - [Description("The text to display in the event of an authentication canceled at the Provider.")] - public string CanceledText { - get { return (string)ViewState[CanceledTextViewStateKey] ?? CanceledTextDefault; } - set { ViewState[CanceledTextViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets a value indicating whether the "Remember Me" checkbox should be displayed. - /// </summary> - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(RememberMeVisibleDefault)] - [Description("Whether the \"Remember Me\" checkbox should be displayed.")] - public bool RememberMeVisible { - get { - EnsureChildControls(); - return this.rememberMeCheckBox.Visible; - } - - set { - EnsureChildControls(); - this.rememberMeCheckBox.Visible = value; - } - } - - /// <summary> - /// Gets or sets a value indicating whether a successful authentication should result in a persistent - /// cookie being saved to the browser. - /// </summary> - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(RememberMeDefault)] - [Description("Whether a successful authentication should result in a persistent cookie being saved to the browser.")] - public bool RememberMe { - get { return this.UsePersistentCookie != LogOnPersistence.Session; } - set { this.UsePersistentCookie = value ? LogOnPersistence.PersistentAuthentication : LogOnPersistence.Session; } - } - - /// <summary> - /// Gets or sets the starting tab index to distribute across the controls. - /// </summary> - [SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow", MessageId = "value+1", Justification = "Overflow would provide desired UI behavior.")] - [SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow", MessageId = "value+2", Justification = "Overflow would provide desired UI behavior.")] - [SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow", MessageId = "value+3", Justification = "Overflow would provide desired UI behavior.")] - public override short TabIndex { - get { - return base.TabIndex; - } - - set { - unchecked { - EnsureChildControls(); - base.TabIndex = (short)(value + TextBoxTabIndexOffset); - this.loginButton.TabIndex = (short)(value + LoginButtonTabIndexOffset); - this.rememberMeCheckBox.TabIndex = (short)(value + RememberMeTabIndexOffset); - this.registerLink.TabIndex = (short)(value + RegisterTabIndexOffset); - } - } - } - - /// <summary> - /// Gets or sets the tooltip to display when the user hovers over the login button. - /// </summary> - [Bindable(true)] - [Category("Appearance")] - [DefaultValue(ButtonToolTipDefault)] - [Localizable(true)] - [Description("The tooltip to display when the user hovers over the login button.")] - public string ButtonToolTip { - get { - EnsureChildControls(); - return this.loginButton.ToolTip; - } - - set { - EnsureChildControls(); - this.loginButton.ToolTip = value; - } - } - - /// <summary> - /// Gets or sets the validation group that the login button and text box validator belong to. - /// </summary> - [Category("Behavior")] - [DefaultValue(ValidationGroupDefault)] - [Description("The validation group that the login button and text box validator belong to.")] - public string ValidationGroup { - get { - EnsureChildControls(); - return this.requiredValidator.ValidationGroup; - } - - set { - EnsureChildControls(); - this.requiredValidator.ValidationGroup = value; - this.loginButton.ValidationGroup = value; - } - } - - /// <summary> - /// Gets or sets the unique hash string that ends your idselector.com account. - /// </summary> - [Category("Behavior")] - [Description("The unique hash string that ends your idselector.com account.")] - public string IdSelectorIdentifier { - get { return (string)(ViewState[IdSelectorIdentifierViewStateKey]); } - set { ViewState[IdSelectorIdentifierViewStateKey] = value; } - } - - #endregion - - #region Properties to hide - - /// <summary> - /// Gets or sets a value indicating whether a FormsAuthentication - /// cookie should persist across user sessions. - /// </summary> - [Browsable(false), Bindable(false)] - public override LogOnPersistence UsePersistentCookie { - get { - return base.UsePersistentCookie; - } - - set { - base.UsePersistentCookie = value; - - if (this.rememberMeCheckBox != null) { - // use conditional here to prevent infinite recursion - // with CheckedChanged event. - bool rememberMe = value != LogOnPersistence.Session; - if (this.rememberMeCheckBox.Checked != rememberMe) { - this.rememberMeCheckBox.Checked = rememberMe; - } - } - } - } - - #endregion - - /// <summary> - /// Outputs server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object and stores tracing information about the control if tracing is enabled. - /// </summary> - /// <param name="writer">The <see cref="T:System.Web.UI.HTmlTextWriter"/> object that receives the control content.</param> - public override void RenderControl(HtmlTextWriter writer) { - this.RenderChildren(writer); - } - - /// <summary> - /// Creates the child controls. - /// </summary> - protected override void CreateChildControls() { - this.InitializeControls(); - - // Just add the panel we've assembled earlier. - base.Controls.Add(this.panel); - } - - /// <summary> - /// Raises the <see cref="E:System.Web.UI.Control.PreRender"/> event. - /// </summary> - /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param> - protected override void OnPreRender(EventArgs e) { - base.OnPreRender(e); - - this.EnsureChildControls(); - } - - /// <summary> - /// Initializes the child controls. - /// </summary> - [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.WebControl.set_ToolTip(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.Label.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.HyperLink.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.CheckBox.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.Button.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.BaseValidator.set_ErrorMessage(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "br", Justification = "HTML"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "OpenID", Justification = "It is correct"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "MyOpenID", Justification = "Correct spelling"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "myopenid", Justification = "URL")] - protected void InitializeControls() { - this.panel = new Panel(); - - Table table = new Table(); - try { - TableRow row1, row2, row3; - TableCell cell; - table.Rows.Add(row1 = new TableRow()); - table.Rows.Add(row2 = new TableRow()); - table.Rows.Add(row3 = new TableRow()); - - // top row, left cell - cell = new TableCell(); - try { - this.label = new HtmlGenericControl("label"); - this.label.InnerText = LabelTextDefault; - cell.Controls.Add(this.label); - row1.Cells.Add(cell); - } catch { - cell.Dispose(); - throw; - } - - // top row, middle cell - cell = new TableCell(); - try { - cell.Controls.Add(new InPlaceControl(this)); - row1.Cells.Add(cell); - } catch { - cell.Dispose(); - throw; - } - - // top row, right cell - cell = new TableCell(); - try { - this.loginButton = new Button(); - this.loginButton.ID = this.ID + "_loginButton"; - this.loginButton.Text = ButtonTextDefault; - this.loginButton.ToolTip = ButtonToolTipDefault; - this.loginButton.Click += this.LoginButton_Click; - this.loginButton.ValidationGroup = ValidationGroupDefault; -#if !Mono - this.panel.DefaultButton = this.loginButton.ID; -#endif - cell.Controls.Add(this.loginButton); - row1.Cells.Add(cell); - } catch { - cell.Dispose(); - throw; - } - - // middle row, left cell - row2.Cells.Add(new TableCell()); - - // middle row, middle cell - cell = new TableCell(); - try { - cell.Style[HtmlTextWriterStyle.Color] = "gray"; - cell.Style[HtmlTextWriterStyle.FontSize] = "smaller"; - this.requiredValidator = new RequiredFieldValidator(); - this.requiredValidator.ErrorMessage = RequiredTextDefault + RequiredTextSuffix; - this.requiredValidator.Text = RequiredTextDefault + RequiredTextSuffix; - this.requiredValidator.Display = ValidatorDisplay.Dynamic; - this.requiredValidator.ValidationGroup = ValidationGroupDefault; - cell.Controls.Add(this.requiredValidator); - this.identifierFormatValidator = new CustomValidator(); - this.identifierFormatValidator.ErrorMessage = UriFormatTextDefault + RequiredTextSuffix; - this.identifierFormatValidator.Text = UriFormatTextDefault + RequiredTextSuffix; - this.identifierFormatValidator.ServerValidate += this.IdentifierFormatValidator_ServerValidate; - this.identifierFormatValidator.Enabled = UriValidatorEnabledDefault; - this.identifierFormatValidator.Display = ValidatorDisplay.Dynamic; - this.identifierFormatValidator.ValidationGroup = ValidationGroupDefault; - cell.Controls.Add(this.identifierFormatValidator); - this.errorLabel = new Label(); - this.errorLabel.EnableViewState = false; - this.errorLabel.ForeColor = System.Drawing.Color.Red; - this.errorLabel.Style[HtmlTextWriterStyle.Display] = "block"; // puts it on its own line - this.errorLabel.Visible = false; - cell.Controls.Add(this.errorLabel); - this.examplePrefixLabel = new Label(); - this.examplePrefixLabel.Text = ExamplePrefixDefault; - cell.Controls.Add(this.examplePrefixLabel); - cell.Controls.Add(new LiteralControl(" ")); - this.exampleUrlLabel = new Label(); - this.exampleUrlLabel.Font.Bold = true; - this.exampleUrlLabel.Text = ExampleUrlDefault; - cell.Controls.Add(this.exampleUrlLabel); - row2.Cells.Add(cell); - } catch { - cell.Dispose(); - throw; - } - - // middle row, right cell - cell = new TableCell(); - try { - cell.Style[HtmlTextWriterStyle.Color] = "gray"; - cell.Style[HtmlTextWriterStyle.FontSize] = "smaller"; - cell.Style[HtmlTextWriterStyle.TextAlign] = "center"; - this.registerLink = new HyperLink(); - this.registerLink.Text = RegisterTextDefault; - this.registerLink.ToolTip = RegisterToolTipDefault; - this.registerLink.NavigateUrl = RegisterUrlDefault; - this.registerLink.Visible = RegisterVisibleDefault; - cell.Controls.Add(this.registerLink); - row2.Cells.Add(cell); - } catch { - cell.Dispose(); - throw; - } - - // bottom row, left cell - cell = new TableCell(); - row3.Cells.Add(cell); - - // bottom row, middle cell - cell = new TableCell(); - try { - this.rememberMeCheckBox = new CheckBox(); - this.rememberMeCheckBox.Text = RememberMeTextDefault; - this.rememberMeCheckBox.Checked = this.UsePersistentCookie != LogOnPersistence.Session; - this.rememberMeCheckBox.Visible = RememberMeVisibleDefault; - this.rememberMeCheckBox.CheckedChanged += this.RememberMeCheckBox_CheckedChanged; - cell.Controls.Add(this.rememberMeCheckBox); - row3.Cells.Add(cell); - } catch { - cell.Dispose(); - throw; - } - - // bottom row, right cell - cell = new TableCell(); - try { - row3.Cells.Add(cell); - } catch { - cell.Dispose(); - throw; - } - - // this sets all the controls' tab indexes - this.TabIndex = TabIndexDefault; - - this.panel.Controls.Add(table); - } catch { - table.Dispose(); - throw; - } - - this.idselectorJavascript = new Literal(); - this.panel.Controls.Add(this.idselectorJavascript); - } - - /// <summary> - /// Raises the <see cref="E:System.Web.UI.Control.Init"/> event. - /// </summary> - /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param> - protected override void OnInit(EventArgs e) { - this.SetChildControlReferenceIds(); - - base.OnInit(e); - } - - /// <summary> - /// Renders the child controls. - /// </summary> - /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the rendered content.</param> - [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.Literal.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "idselector", Justification = "HTML"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "charset", Justification = "html"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "src", Justification = "html"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "openidselector", Justification = "html"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "idselectorinputid", Justification = "html")] - protected override void RenderChildren(HtmlTextWriter writer) { - if (!this.DesignMode) { - this.label.Attributes["for"] = this.ClientID; - - if (!string.IsNullOrEmpty(this.IdSelectorIdentifier)) { - this.idselectorJavascript.Visible = true; - this.idselectorJavascript.Text = @"<script type='text/javascript'><!-- -idselector_input_id = '" + this.ClientID + @"'; -// --></script> -<script type='text/javascript' id='__openidselector' src='https://www.idselector.com/selector/" + this.IdSelectorIdentifier + @"' charset='utf-8'></script>"; - } else { - this.idselectorJavascript.Visible = false; - } - } - - base.RenderChildren(writer); - } - - /// <summary> - /// Adds failure handling to display an error message to the user. - /// </summary> - /// <param name="response">The response.</param> - protected override void OnFailed(IAuthenticationResponse response) { - base.OnFailed(response); - - if (!string.IsNullOrEmpty(this.FailedMessageText)) { - this.errorLabel.Text = string.Format(CultureInfo.CurrentCulture, this.FailedMessageText, response.Exception.ToStringDescriptive()); - this.errorLabel.Visible = true; - } - } - - /// <summary> - /// Adds authentication cancellation behavior to display a message to the user. - /// </summary> - /// <param name="response">The response.</param> - protected override void OnCanceled(IAuthenticationResponse response) { - base.OnCanceled(response); - - if (!string.IsNullOrEmpty(this.CanceledText)) { - this.errorLabel.Text = this.CanceledText; - this.errorLabel.Visible = true; - } - } - - /// <summary> - /// Fires the <see cref="RememberMeChanged"/> event. - /// </summary> - protected virtual void OnRememberMeChanged() { - EventHandler rememberMeChanged = this.RememberMeChanged; - if (rememberMeChanged != null) { - rememberMeChanged(this, new EventArgs()); - } - } - - /// <summary> - /// Handles the ServerValidate event of the identifierFormatValidator control. - /// </summary> - /// <param name="source">The source of the event.</param> - /// <param name="args">The <see cref="System.Web.UI.WebControls.ServerValidateEventArgs"/> instance containing the event data.</param> - private void IdentifierFormatValidator_ServerValidate(object source, ServerValidateEventArgs args) { - args.IsValid = Identifier.IsValid(args.Value); - } - - /// <summary> - /// Handles the CheckedChanged event of the rememberMeCheckBox control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> - private void RememberMeCheckBox_CheckedChanged(object sender, EventArgs e) { - this.RememberMe = this.rememberMeCheckBox.Checked; - this.OnRememberMeChanged(); - } - - /// <summary> - /// Handles the Click event of the loginButton control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> - private void LoginButton_Click(object sender, EventArgs e) { - if (!this.Page.IsValid) { - return; - } - - IAuthenticationRequest request = this.CreateRequests().FirstOrDefault(); - if (request != null) { - this.LogOn(request); - } else { - if (!string.IsNullOrEmpty(this.FailedMessageText)) { - this.errorLabel.Text = string.Format(CultureInfo.CurrentCulture, this.FailedMessageText, OpenIdStrings.OpenIdEndpointNotFound); - this.errorLabel.Visible = true; - } - } - } - - /// <summary> - /// Renders the control inner. - /// </summary> - /// <param name="writer">The writer.</param> - private void RenderControlInner(HtmlTextWriter writer) { - base.RenderControl(writer); - } - - /// <summary> - /// Sets child control properties that depend on this control's ID. - /// </summary> - private void SetChildControlReferenceIds() { - this.EnsureChildControls(); - this.EnsureID(); - ErrorUtilities.VerifyInternal(!string.IsNullOrEmpty(this.ID), "No control ID available yet!"); - this.requiredValidator.ControlToValidate = this.ID; - this.requiredValidator.ID = this.ID + "_requiredValidator"; - this.identifierFormatValidator.ControlToValidate = this.ID; - this.identifierFormatValidator.ID = this.ID + "_identifierFormatValidator"; - } - - /// <summary> - /// A control that acts as a placeholder to indicate where - /// the OpenIdLogin control should render its OpenIdTextBox parent. - /// </summary> - private class InPlaceControl : PlaceHolder { - /// <summary> - /// The owning control to render. - /// </summary> - private OpenIdLogin renderControl; - - /// <summary> - /// Initializes a new instance of the <see cref="InPlaceControl"/> class. - /// </summary> - /// <param name="renderControl">The render control.</param> - internal InPlaceControl(OpenIdLogin renderControl) { - this.renderControl = renderControl; - } - - /// <summary> - /// Sends server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object, which writes the content to be rendered on the client. - /// </summary> - /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param> - protected override void Render(HtmlTextWriter writer) { - this.renderControl.RenderControlInner(writer); - } - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdMobileTextBox.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdMobileTextBox.cs deleted file mode 100644 index fc80b32..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdMobileTextBox.cs +++ /dev/null @@ -1,778 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdMobileTextBox.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -[assembly: System.Web.UI.WebResource(DotNetOpenAuth.OpenId.RelyingParty.OpenIdMobileTextBox.EmbeddedLogoResourceName, "image/gif")] - -namespace DotNetOpenAuth.OpenId.RelyingParty { - using System; - using System.ComponentModel; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.Diagnostics.Contracts; - using System.Globalization; - using System.Text.RegularExpressions; - using System.Web.Security; - using System.Web.UI; - using System.Web.UI.MobileControls; - using DotNetOpenAuth.Configuration; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration; - - /// <summary> - /// An ASP.NET control for mobile devices that provides a minimal text box that is OpenID-aware. - /// </summary> - [DefaultProperty("Text"), ValidationProperty("Text")] - [ToolboxData("<{0}:OpenIdMobileTextBox runat=\"server\" />")] - public class OpenIdMobileTextBox : TextBox { - /// <summary> - /// The name of the manifest stream containing the - /// OpenID logo that is placed inside the text box. - /// </summary> - internal const string EmbeddedLogoResourceName = OpenIdTextBox.EmbeddedLogoResourceName; - - /// <summary> - /// Default value of <see cref="UsePersistentCookie"/>. - /// </summary> - protected const bool UsePersistentCookieDefault = false; - - #region Property category constants - - /// <summary> - /// The "Appearance" category for properties. - /// </summary> - private const string AppearanceCategory = "Appearance"; - - /// <summary> - /// The "Simple Registration" category for properties. - /// </summary> - private const string ProfileCategory = "Simple Registration"; - - /// <summary> - /// The "Behavior" category for properties. - /// </summary> - private const string BehaviorCategory = "Behavior"; - - #endregion - - #region Property viewstate keys - - /// <summary> - /// The viewstate key to use for the <see cref="RequestEmail"/> property. - /// </summary> - private const string RequestEmailViewStateKey = "RequestEmail"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestNickname"/> property. - /// </summary> - private const string RequestNicknameViewStateKey = "RequestNickname"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestPostalCode"/> property. - /// </summary> - private const string RequestPostalCodeViewStateKey = "RequestPostalCode"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestCountry"/> property. - /// </summary> - private const string RequestCountryViewStateKey = "RequestCountry"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequireSsl"/> property. - /// </summary> - private const string RequireSslViewStateKey = "RequireSsl"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestLanguage"/> property. - /// </summary> - private const string RequestLanguageViewStateKey = "RequestLanguage"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestTimeZone"/> property. - /// </summary> - private const string RequestTimeZoneViewStateKey = "RequestTimeZone"; - - /// <summary> - /// The viewstate key to use for the <see cref="EnableRequestProfile"/> property. - /// </summary> - private const string EnableRequestProfileViewStateKey = "EnableRequestProfile"; - - /// <summary> - /// The viewstate key to use for the <see cref="PolicyUrl"/> property. - /// </summary> - private const string PolicyUrlViewStateKey = "PolicyUrl"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestFullName"/> property. - /// </summary> - private const string RequestFullNameViewStateKey = "RequestFullName"; - - /// <summary> - /// The viewstate key to use for the <see cref="UsePersistentCookie"/> property. - /// </summary> - private const string UsePersistentCookieViewStateKey = "UsePersistentCookie"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestGender"/> property. - /// </summary> - private const string RequestGenderViewStateKey = "RequestGender"; - - /// <summary> - /// The viewstate key to use for the <see cref="ReturnToUrl"/> property. - /// </summary> - private const string ReturnToUrlViewStateKey = "ReturnToUrl"; - - /// <summary> - /// The viewstate key to use for the <see cref="Stateless"/> property. - /// </summary> - private const string StatelessViewStateKey = "Stateless"; - - /// <summary> - /// The viewstate key to use for the <see cref="ImmediateMode"/> property. - /// </summary> - private const string ImmediateModeViewStateKey = "ImmediateMode"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestBirthDate"/> property. - /// </summary> - private const string RequestBirthDateViewStateKey = "RequestBirthDate"; - - /// <summary> - /// The viewstate key to use for the <see cref="RealmUrl"/> property. - /// </summary> - private const string RealmUrlViewStateKey = "RealmUrl"; - - #endregion - - #region Property defaults - - /// <summary> - /// The default value for the <see cref="EnableRequestProfile"/> property. - /// </summary> - private const bool EnableRequestProfileDefault = true; - - /// <summary> - /// The default value for the <see cref="RequireSsl"/> property. - /// </summary> - private const bool RequireSslDefault = false; - - /// <summary> - /// The default value for the <see cref="ImmediateMode"/> property. - /// </summary> - private const bool ImmediateModeDefault = false; - - /// <summary> - /// The default value for the <see cref="Stateless"/> property. - /// </summary> - private const bool StatelessDefault = false; - - /// <summary> - /// The default value for the <see cref="PolicyUrl"/> property. - /// </summary> - private const string PolicyUrlDefault = ""; - - /// <summary> - /// The default value for the <see cref="ReturnToUrl"/> property. - /// </summary> - private const string ReturnToUrlDefault = ""; - - /// <summary> - /// The default value for the <see cref="RealmUrl"/> property. - /// </summary> - private const string RealmUrlDefault = "~/"; - - /// <summary> - /// The default value for the <see cref="RequestEmail"/> property. - /// </summary> - private const DemandLevel RequestEmailDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestPostalCode"/> property. - /// </summary> - private const DemandLevel RequestPostalCodeDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestCountry"/> property. - /// </summary> - private const DemandLevel RequestCountryDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestLanguage"/> property. - /// </summary> - private const DemandLevel RequestLanguageDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestTimeZone"/> property. - /// </summary> - private const DemandLevel RequestTimeZoneDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestNickname"/> property. - /// </summary> - private const DemandLevel RequestNicknameDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestFullName"/> property. - /// </summary> - private const DemandLevel RequestFullNameDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestBirthDate"/> property. - /// </summary> - private const DemandLevel RequestBirthDateDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestGender"/> property. - /// </summary> - private const DemandLevel RequestGenderDefault = DemandLevel.NoRequest; - - #endregion - - /// <summary> - /// The callback parameter for use with persisting the <see cref="UsePersistentCookie"/> property. - /// </summary> - private const string UsePersistentCookieCallbackKey = "OpenIdTextBox_UsePersistentCookie"; - - /// <summary> - /// Backing field for the <see cref="RelyingParty"/> property. - /// </summary> - private OpenIdRelyingParty relyingParty; - - /// <summary> - /// Initializes a new instance of the <see cref="OpenIdMobileTextBox"/> class. - /// </summary> - public OpenIdMobileTextBox() { - Reporting.RecordFeatureUse(this); - } - - #region Events - - /// <summary> - /// Fired upon completion of a successful login. - /// </summary> - [Description("Fired upon completion of a successful login.")] - public event EventHandler<OpenIdEventArgs> LoggedIn; - - /// <summary> - /// Fired when a login attempt fails. - /// </summary> - [Description("Fired when a login attempt fails.")] - public event EventHandler<OpenIdEventArgs> Failed; - - /// <summary> - /// Fired when an authentication attempt is canceled at the OpenID Provider. - /// </summary> - [Description("Fired when an authentication attempt is canceled at the OpenID Provider.")] - public event EventHandler<OpenIdEventArgs> Canceled; - - /// <summary> - /// Fired when an Immediate authentication attempt fails, and the Provider suggests using non-Immediate mode. - /// </summary> - [Description("Fired when an Immediate authentication attempt fails, and the Provider suggests using non-Immediate mode.")] - public event EventHandler<OpenIdEventArgs> SetupRequired; - - #endregion - - #region Properties - - /// <summary> - /// Gets or sets the OpenID <see cref="Realm"/> of the relying party web site. - /// </summary> - [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "DotNetOpenAuth.OpenId.Realm", Justification = "Using Realm.ctor for validation.")] - [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.Uri", Justification = "Using Uri.ctor for validation.")] - [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "DotNetOpenAuth.OpenId", Justification = "Using ctor for validation.")] - [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Bindable property must be simple type")] - [Bindable(true), DefaultValue(RealmUrlDefault), Category(BehaviorCategory)] - [Description("The OpenID Realm of the relying party web site.")] - public string RealmUrl { - get { - return (string)(ViewState[RealmUrlViewStateKey] ?? RealmUrlDefault); - } - - set { - if (Page != null && !DesignMode) { - // Validate new value by trying to construct a Realm object based on it. - new Realm(OpenIdUtilities.GetResolvedRealm(this.Page, value, this.RelyingParty.Channel.GetRequestFromContext())); // throws an exception on failure. - } else { - // We can't fully test it, but it should start with either ~/ or a protocol. - if (Regex.IsMatch(value, @"^https?://")) { - new Uri(value.Replace("*.", string.Empty)); // make sure it's fully-qualified, but ignore wildcards - } else if (value.StartsWith("~/", StringComparison.Ordinal)) { - // this is valid too - } else { - throw new UriFormatException(); - } - } - ViewState[RealmUrlViewStateKey] = value; - } - } - - /// <summary> - /// Gets or sets the OpenID ReturnTo of the relying party web site. - /// </summary> - [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Uri(Uri, string) accepts second arguments that Uri(Uri, new Uri(string)) does not that we must support.")] - [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.Uri", Justification = "Using Uri.ctor for validation.")] - [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Bindable property must be simple type")] - [Bindable(true), DefaultValue(ReturnToUrlDefault), Category(BehaviorCategory)] - [Description("The OpenID ReturnTo of the relying party web site.")] - public string ReturnToUrl { - get { - return (string)(ViewState[ReturnToUrlViewStateKey] ?? ReturnToUrlDefault); - } - - set { - if (Page != null && !DesignMode) { - // Validate new value by trying to construct a Uri based on it. - new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.Page.ResolveUrl(value)); // throws an exception on failure. - } else { - // We can't fully test it, but it should start with either ~/ or a protocol. - if (Regex.IsMatch(value, @"^https?://")) { - new Uri(value); // make sure it's fully-qualified, but ignore wildcards - } else if (value.StartsWith("~/", StringComparison.Ordinal)) { - // this is valid too - } else { - throw new UriFormatException(); - } - } - - ViewState[ReturnToUrlViewStateKey] = value; - } - } - - /// <summary> - /// Gets or sets a value indicating whether to use immediate mode in the - /// OpenID protocol. - /// </summary> - /// <value> - /// True if a Provider should reply immediately to the authentication request - /// without interacting with the user. False if the Provider can take time - /// to authenticate the user in order to complete an authentication attempt. - /// </value> - /// <remarks> - /// Setting this to true is sometimes useful in AJAX scenarios. Setting this to - /// true can cause failed authentications when the user truly controls an - /// Identifier, but must complete an authentication step with the Provider before - /// the Provider will approve the login from this relying party. - /// </remarks> - [Bindable(true), DefaultValue(ImmediateModeDefault), Category(BehaviorCategory)] - [Description("Whether the Provider should respond immediately to an authentication attempt without interacting with the user.")] - public bool ImmediateMode { - get { return (bool)(ViewState[ImmediateModeViewStateKey] ?? ImmediateModeDefault); } - set { ViewState[ImmediateModeViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets a value indicating whether stateless mode is used. - /// </summary> - [Bindable(true), DefaultValue(StatelessDefault), Category(BehaviorCategory)] - [Description("Controls whether stateless mode is used.")] - public bool Stateless { - get { return (bool)(ViewState[StatelessViewStateKey] ?? StatelessDefault); } - set { ViewState[StatelessViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets a value indicating whether to send a persistent cookie upon successful - /// login so the user does not have to log in upon returning to this site. - /// </summary> - [Bindable(true), DefaultValue(UsePersistentCookieDefault), Category(BehaviorCategory)] - [Description("Whether to send a persistent cookie upon successful " + - "login so the user does not have to log in upon returning to this site.")] - public virtual bool UsePersistentCookie { - get { return (bool)(this.ViewState[UsePersistentCookieViewStateKey] ?? UsePersistentCookieDefault); } - set { this.ViewState[UsePersistentCookieViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's nickname from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestNicknameDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's nickname from the Provider.")] - public DemandLevel RequestNickname { - get { return (DemandLevel)(ViewState[RequestNicknameViewStateKey] ?? RequestNicknameDefault); } - set { ViewState[RequestNicknameViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's email address from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestEmailDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's email address from the Provider.")] - public DemandLevel RequestEmail { - get { return (DemandLevel)(ViewState[RequestEmailViewStateKey] ?? RequestEmailDefault); } - set { ViewState[RequestEmailViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's full name from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestFullNameDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's full name from the Provider")] - public DemandLevel RequestFullName { - get { return (DemandLevel)(ViewState[RequestFullNameViewStateKey] ?? RequestFullNameDefault); } - set { ViewState[RequestFullNameViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's birthdate from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestBirthDateDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's birthdate from the Provider.")] - public DemandLevel RequestBirthDate { - get { return (DemandLevel)(ViewState[RequestBirthDateViewStateKey] ?? RequestBirthDateDefault); } - set { ViewState[RequestBirthDateViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's gender from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestGenderDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's gender from the Provider.")] - public DemandLevel RequestGender { - get { return (DemandLevel)(ViewState[RequestGenderViewStateKey] ?? RequestGenderDefault); } - set { ViewState[RequestGenderViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's postal code from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestPostalCodeDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's postal code from the Provider.")] - public DemandLevel RequestPostalCode { - get { return (DemandLevel)(ViewState[RequestPostalCodeViewStateKey] ?? RequestPostalCodeDefault); } - set { ViewState[RequestPostalCodeViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's country from the Provider. - /// </summary> - [Bindable(true)] - [Category(ProfileCategory)] - [DefaultValue(RequestCountryDefault)] - [Description("Your level of interest in receiving the user's country from the Provider.")] - public DemandLevel RequestCountry { - get { return (DemandLevel)(ViewState[RequestCountryViewStateKey] ?? RequestCountryDefault); } - set { ViewState[RequestCountryViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's preferred language from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestLanguageDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's preferred language from the Provider.")] - public DemandLevel RequestLanguage { - get { return (DemandLevel)(ViewState[RequestLanguageViewStateKey] ?? RequestLanguageDefault); } - set { ViewState[RequestLanguageViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's time zone from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestTimeZoneDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's time zone from the Provider.")] - public DemandLevel RequestTimeZone { - get { return (DemandLevel)(ViewState[RequestTimeZoneViewStateKey] ?? RequestTimeZoneDefault); } - set { ViewState[RequestTimeZoneViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the URL to your privacy policy page that describes how - /// claims will be used and/or shared. - /// </summary> - [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Bindable property must be simple type")] - [Bindable(true), DefaultValue(PolicyUrlDefault), Category(ProfileCategory)] - [Description("The URL to your privacy policy page that describes how claims will be used and/or shared.")] - public string PolicyUrl { - get { - return (string)ViewState[PolicyUrlViewStateKey] ?? PolicyUrlDefault; - } - - set { - UriUtil.ValidateResolvableUrl(Page, DesignMode, value); - ViewState[PolicyUrlViewStateKey] = value; - } - } - - /// <summary> - /// Gets or sets a value indicating whether to use OpenID extensions - /// to retrieve profile data of the authenticating user. - /// </summary> - [Bindable(true), DefaultValue(EnableRequestProfileDefault), Category(ProfileCategory)] - [Description("Turns the entire Simple Registration extension on or off.")] - public bool EnableRequestProfile { - get { return (bool)(ViewState[EnableRequestProfileViewStateKey] ?? EnableRequestProfileDefault); } - set { ViewState[EnableRequestProfileViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets a value indicating whether to enforce on high security mode, - /// which requires the full authentication pipeline to be protected by SSL. - /// </summary> - [Bindable(true), DefaultValue(RequireSslDefault), Category(BehaviorCategory)] - [Description("Turns on high security mode, requiring the full authentication pipeline to be protected by SSL.")] - public bool RequireSsl { - get { return (bool)(ViewState[RequireSslViewStateKey] ?? RequireSslDefault); } - set { ViewState[RequireSslViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the type of the custom application store to use, or <c>null</c> to use the default. - /// </summary> - /// <remarks> - /// If set, this property must be set in each Page Load event - /// as it is not persisted across postbacks. - /// </remarks> - public IOpenIdApplicationStore CustomApplicationStore { get; set; } - - #endregion - - /// <summary> - /// Gets or sets the <see cref="OpenIdRelyingParty"/> instance to use. - /// </summary> - /// <value>The default value is an <see cref="OpenIdRelyingParty"/> instance initialized according to the web.config file.</value> - /// <remarks> - /// A performance optimization would be to store off the - /// instance as a static member in your web site and set it - /// to this property in your <see cref="Control.Load">Page.Load</see> - /// event since instantiating these instances can be expensive on - /// heavily trafficked web pages. - /// </remarks> - public OpenIdRelyingParty RelyingParty { - get { - if (this.relyingParty == null) { - this.relyingParty = this.CreateRelyingParty(); - } - return this.relyingParty; - } - - set { - this.relyingParty = value; - } - } - - /// <summary> - /// Gets or sets the OpenID authentication request that is about to be sent. - /// </summary> - protected IAuthenticationRequest Request { get; set; } - - /// <summary> - /// Immediately redirects to the OpenID Provider to verify the Identifier - /// provided in the text box. - /// </summary> - public void LogOn() { - if (this.Request == null) { - this.CreateRequest(); // sets this.Request - } - - if (this.Request != null) { - this.Request.RedirectToProvider(); - } - } - - /// <summary> - /// Constructs the authentication request and returns it. - /// </summary> - /// <returns>The instantiated authentication request.</returns> - /// <remarks> - /// <para>This method need not be called before calling the <see cref="LogOn"/> method, - /// but is offered in the event that adding extensions to the request is desired.</para> - /// <para>The Simple Registration extension arguments are added to the request - /// before returning if <see cref="EnableRequestProfile"/> is set to true.</para> - /// </remarks> - [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Uri(Uri, string) accepts second arguments that Uri(Uri, new Uri(string)) does not that we must support.")] - public IAuthenticationRequest CreateRequest() { - Contract.Requires<InvalidOperationException>(this.Request == null, OpenIdStrings.CreateRequestAlreadyCalled); - Contract.Requires<InvalidOperationException>(!string.IsNullOrEmpty(this.Text), OpenIdStrings.OpenIdTextBoxEmpty); - - try { - // 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 = Page.Request.Url.Scheme; - realm.Port = Page.Request.Url.Port; - - // Initiate openid request - // We use TryParse here to avoid throwing an exception which - // might slip through our validator control if it is disabled. - Identifier userSuppliedIdentifier; - if (Identifier.TryParse(this.Text, out userSuppliedIdentifier)) { - Realm typedRealm = new Realm(realm); - if (string.IsNullOrEmpty(this.ReturnToUrl)) { - this.Request = this.RelyingParty.CreateRequest(userSuppliedIdentifier, typedRealm); - } else { - Uri returnTo = new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.ReturnToUrl); - this.Request = this.RelyingParty.CreateRequest(userSuppliedIdentifier, typedRealm, returnTo); - } - this.Request.Mode = this.ImmediateMode ? AuthenticationRequestMode.Immediate : AuthenticationRequestMode.Setup; - if (this.EnableRequestProfile) { - this.AddProfileArgs(this.Request); - } - - // Add state that needs to survive across the redirect. - this.Request.SetUntrustedCallbackArgument(UsePersistentCookieCallbackKey, this.UsePersistentCookie.ToString(CultureInfo.InvariantCulture)); - } else { - Logger.OpenId.WarnFormat("An invalid identifier was entered ({0}), but not caught by any validation routine.", this.Text); - this.Request = null; - } - } catch (ProtocolException ex) { - this.OnFailed(new FailedAuthenticationResponse(ex)); - } - - return this.Request; - } - - /// <summary> - /// Checks for incoming OpenID authentication responses and fires appropriate events. - /// </summary> - /// <param name="e">The <see cref="T:System.EventArgs"/> object that contains the event data.</param> - protected override void OnLoad(EventArgs e) { - base.OnLoad(e); - - if (Page.IsPostBack) { - return; - } - - var response = this.RelyingParty.GetResponse(); - if (response != null) { - string persistentString = response.GetUntrustedCallbackArgument(UsePersistentCookieCallbackKey); - bool persistentBool; - if (persistentString != null && bool.TryParse(persistentString, out persistentBool)) { - this.UsePersistentCookie = persistentBool; - } - - switch (response.Status) { - case AuthenticationStatus.Canceled: - this.OnCanceled(response); - break; - case AuthenticationStatus.Authenticated: - this.OnLoggedIn(response); - break; - case AuthenticationStatus.SetupRequired: - this.OnSetupRequired(response); - break; - case AuthenticationStatus.Failed: - this.OnFailed(response); - break; - default: - throw new InvalidOperationException("Unexpected response status code."); - } - } - } - - #region Events - - /// <summary> - /// Fires the <see cref="LoggedIn"/> event. - /// </summary> - /// <param name="response">The response.</param> - protected virtual void OnLoggedIn(IAuthenticationResponse response) { - Contract.Requires<ArgumentNullException>(response != null); - ErrorUtilities.VerifyInternal(response.Status == AuthenticationStatus.Authenticated, "Firing OnLoggedIn event without an authenticated response."); - - var loggedIn = this.LoggedIn; - OpenIdEventArgs args = new OpenIdEventArgs(response); - if (loggedIn != null) { - loggedIn(this, args); - } - - if (!args.Cancel) { - FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, this.UsePersistentCookie); - } - } - - /// <summary> - /// Fires the <see cref="Failed"/> event. - /// </summary> - /// <param name="response">The response.</param> - protected virtual void OnFailed(IAuthenticationResponse response) { - Contract.Requires<ArgumentNullException>(response != null); - ErrorUtilities.VerifyInternal(response.Status == AuthenticationStatus.Failed, "Firing Failed event for the wrong response type."); - - var failed = this.Failed; - if (failed != null) { - failed(this, new OpenIdEventArgs(response)); - } - } - - /// <summary> - /// Fires the <see cref="Canceled"/> event. - /// </summary> - /// <param name="response">The response.</param> - protected virtual void OnCanceled(IAuthenticationResponse response) { - Contract.Requires<ArgumentNullException>(response != null); - ErrorUtilities.VerifyInternal(response.Status == AuthenticationStatus.Canceled, "Firing Canceled event for the wrong response type."); - - var canceled = this.Canceled; - if (canceled != null) { - canceled(this, new OpenIdEventArgs(response)); - } - } - - /// <summary> - /// Fires the <see cref="SetupRequired"/> event. - /// </summary> - /// <param name="response">The response.</param> - protected virtual void OnSetupRequired(IAuthenticationResponse response) { - Contract.Requires<ArgumentNullException>(response != null); - ErrorUtilities.VerifyInternal(response.Status == AuthenticationStatus.SetupRequired, "Firing SetupRequired event for the wrong response type."); - - // Why are we firing Failed when we're OnSetupRequired? Backward compatibility. - var setupRequired = this.SetupRequired; - if (setupRequired != null) { - setupRequired(this, new OpenIdEventArgs(response)); - } - } - - #endregion - - /// <summary> - /// Adds extensions to a given authentication request to ask the Provider - /// for user profile data. - /// </summary> - /// <param name="request">The authentication request to add the extensions to.</param> - private void AddProfileArgs(IAuthenticationRequest request) { - Contract.Requires<ArgumentNullException>(request != null); - - request.AddExtension(new ClaimsRequest() { - Nickname = this.RequestNickname, - Email = this.RequestEmail, - FullName = this.RequestFullName, - BirthDate = this.RequestBirthDate, - Gender = this.RequestGender, - PostalCode = this.RequestPostalCode, - Country = this.RequestCountry, - Language = this.RequestLanguage, - TimeZone = this.RequestTimeZone, - PolicyUrl = string.IsNullOrEmpty(this.PolicyUrl) ? - null : new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.Page.ResolveUrl(this.PolicyUrl)), - }); - } - - /// <summary> - /// Creates the relying party instance used to generate authentication requests. - /// </summary> - /// <returns>The instantiated relying party.</returns> - private OpenIdRelyingParty CreateRelyingParty() { - // If we're in stateful mode, first use the explicitly given one on this control if there - // is one. Then try the configuration file specified one. Finally, use the default - // in-memory one that's built into OpenIdRelyingParty. - IOpenIdApplicationStore store = this.Stateless ? null : - (this.CustomApplicationStore ?? OpenIdElement.Configuration.RelyingParty.ApplicationStore.CreateInstance(OpenIdRelyingParty.HttpApplicationStore)); - var rp = new OpenIdRelyingParty(store); - try { - // Only set RequireSsl to true, as we don't want to override - // a .config setting of true with false. - if (this.RequireSsl) { - rp.SecuritySettings.RequireSsl = true; - } - return rp; - } catch { - rp.Dispose(); - throw; - } - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs deleted file mode 100644 index eaaba8c..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs +++ /dev/null @@ -1,468 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdRelyingPartyAjaxControlBase.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -[assembly: System.Web.UI.WebResource(DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyAjaxControlBase.EmbeddedAjaxJavascriptResource, "text/javascript")] - -namespace DotNetOpenAuth.OpenId.RelyingParty { - using System; - using System.Collections.Generic; - using System.ComponentModel; - using System.Diagnostics.CodeAnalysis; - using System.Diagnostics.Contracts; - using System.Globalization; - using System.Linq; - using System.Text; - using System.Web; - using System.Web.Script.Serialization; - using System.Web.UI; - using DotNetOpenAuth.Configuration; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OpenId.Extensions; - - /// <summary> - /// A common base class for OpenID Relying Party controls. - /// </summary> - public abstract class OpenIdRelyingPartyAjaxControlBase : OpenIdRelyingPartyControlBase, ICallbackEventHandler { - /// <summary> - /// The manifest resource name of the javascript file to include on the hosting page. - /// </summary> - internal const string EmbeddedAjaxJavascriptResource = Util.DefaultNamespace + ".OpenId.RelyingParty.OpenIdRelyingPartyAjaxControlBase.js"; - - /// <summary> - /// The "dnoa.op_endpoint" string. - /// </summary> - internal const string OPEndpointParameterName = OpenIdUtilities.CustomParameterPrefix + "op_endpoint"; - - /// <summary> - /// The "dnoa.claimed_id" string. - /// </summary> - internal const string ClaimedIdParameterName = OpenIdUtilities.CustomParameterPrefix + "claimed_id"; - - /// <summary> - /// The name of the javascript field that stores the maximum time a positive assertion is - /// good for before it must be refreshed. - /// </summary> - internal const string MaxPositiveAssertionLifetimeJsName = "window.dnoa_internal.maxPositiveAssertionLifetime"; - - /// <summary> - /// The name of the javascript function that will initiate an asynchronous callback. - /// </summary> - protected internal const string CallbackJSFunctionAsync = "window.dnoa_internal.callbackAsync"; - - /// <summary> - /// The name of the javascript function that will initiate a synchronous callback. - /// </summary> - protected const string CallbackJSFunction = "window.dnoa_internal.callback"; - - #region Property viewstate keys - - /// <summary> - /// The viewstate key to use for storing the value of a successful authentication. - /// </summary> - private const string AuthDataViewStateKey = "AuthData"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="AuthenticationResponse"/> property. - /// </summary> - private const string AuthenticationResponseViewStateKey = "AuthenticationResponse"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="AuthenticationProcessedAlready"/> property. - /// </summary> - private const string AuthenticationProcessedAlreadyViewStateKey = "AuthenticationProcessedAlready"; - - #endregion - - /// <summary> - /// Default value of the <see cref="Popup"/> property. - /// </summary> - private const PopupBehavior PopupDefault = PopupBehavior.Always; - - /// <summary> - /// Default value of <see cref="LogOnMode"/> property.. - /// </summary> - private const LogOnSiteNotification LogOnModeDefault = LogOnSiteNotification.None; - - /// <summary> - /// The authentication response that just came in. - /// </summary> - private IAuthenticationResponse authenticationResponse; - - /// <summary> - /// Stores the result of an AJAX discovery request while it is waiting - /// to be picked up by ASP.NET on the way down to the user agent. - /// </summary> - private string discoveryResult; - - /// <summary> - /// Initializes a new instance of the <see cref="OpenIdRelyingPartyAjaxControlBase"/> class. - /// </summary> - protected OpenIdRelyingPartyAjaxControlBase() { - // The AJAX login style always uses popups (or invisible iframes). - base.Popup = PopupDefault; - - // The expected use case for the AJAX login box is for comments... not logging in. - this.LogOnMode = LogOnModeDefault; - } - - /// <summary> - /// Fired when a Provider sends back a positive assertion to this control, - /// but the authentication has not yet been verified. - /// </summary> - /// <remarks> - /// <b>No security critical decisions should be made within event handlers - /// for this event</b> as the authenticity of the assertion has not been - /// verified yet. All security related code should go in the event handler - /// for the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event. - /// </remarks> - [Description("Fired when a Provider sends back a positive assertion to this control, but the authentication has not yet been verified.")] - public event EventHandler<OpenIdEventArgs> UnconfirmedPositiveAssertion; - - /// <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(false), Browsable(false), DefaultValue(PopupDefault)] - public override PopupBehavior Popup { - get { return base.Popup; } - set { ErrorUtilities.VerifySupported(value == base.Popup, OpenIdStrings.PropertyValueNotSupported); } - } - - /// <summary> - /// Gets or sets the way a completed login is communicated to the rest of the web site. - /// </summary> - [Bindable(true), DefaultValue(LogOnModeDefault), Category(BehaviorCategory)] - [Description("The way a completed login is communicated to the rest of the web site.")] - public override LogOnSiteNotification LogOnMode { // override to set new DefaultValue - get { return base.LogOnMode; } - set { base.LogOnMode = value; } - } - - /// <summary> - /// Gets or sets the <see cref="OpenIdRelyingParty"/> instance to use. - /// </summary> - /// <value> - /// The default value is an <see cref="OpenIdRelyingParty"/> instance initialized according to the web.config file. - /// </value> - /// <remarks> - /// A performance optimization would be to store off the - /// instance as a static member in your web site and set it - /// to this property in your <see cref="Control.Load">Page.Load</see> - /// event since instantiating these instances can be expensive on - /// heavily trafficked web pages. - /// </remarks> - public override OpenIdRelyingParty RelyingParty { - get { - return base.RelyingParty; - } - - set { - // Make sure we get an AJAX-ready instance. - ErrorUtilities.VerifyArgument(value is OpenIdAjaxRelyingParty, OpenIdStrings.TypeMustImplementX, typeof(OpenIdAjaxRelyingParty).Name); - base.RelyingParty = value; - } - } - - /// <summary> - /// Gets the completed authentication response. - /// </summary> - public IAuthenticationResponse AuthenticationResponse { - get { - if (this.authenticationResponse == null) { - // We will either validate a new response and return a live AuthenticationResponse - // or we will try to deserialize a previous IAuthenticationResponse (snapshot) - // from viewstate and return that. - IAuthenticationResponse viewstateResponse = this.ViewState[AuthenticationResponseViewStateKey] as IAuthenticationResponse; - string viewstateAuthData = this.ViewState[AuthDataViewStateKey] as string; - string formAuthData = this.Page.Request.Form[this.OpenIdAuthDataFormKey]; - - // First see if there is fresh auth data to be processed into a response. - if (!string.IsNullOrEmpty(formAuthData) && !string.Equals(viewstateAuthData, formAuthData, StringComparison.Ordinal)) { - this.ViewState[AuthDataViewStateKey] = formAuthData; - - Uri authUri = new Uri(formAuthData); - HttpRequestInfo clientResponseInfo = new HttpRequestInfo { - UrlBeforeRewriting = authUri, - }; - - this.authenticationResponse = this.RelyingParty.GetResponse(clientResponseInfo); - Logger.Controls.DebugFormat( - "The {0} control checked for an authentication response and found: {1}", - this.ID, - this.authenticationResponse.Status); - this.AuthenticationProcessedAlready = false; - - // Save out the authentication response to viewstate so we can find it on - // a subsequent postback. - this.ViewState[AuthenticationResponseViewStateKey] = new PositiveAuthenticationResponseSnapshot(this.authenticationResponse); - } else { - this.authenticationResponse = viewstateResponse; - } - } - - return this.authenticationResponse; - } - } - - /// <summary> - /// Gets the relying party as its AJAX type. - /// </summary> - protected OpenIdAjaxRelyingParty AjaxRelyingParty { - get { return (OpenIdAjaxRelyingParty)this.RelyingParty; } - } - - /// <summary> - /// Gets the name of the open id auth data form key (for the value as stored at the user agent as a FORM field). - /// </summary> - /// <value>Usually a concatenation of the control's name and <c>"_openidAuthData"</c>.</value> - protected abstract string OpenIdAuthDataFormKey { get; } - - /// <summary> - /// Gets or sets a value indicating whether an authentication in the page's view state - /// has already been processed and appropriate events fired. - /// </summary> - private bool AuthenticationProcessedAlready { - get { return (bool)(ViewState[AuthenticationProcessedAlreadyViewStateKey] ?? false); } - set { ViewState[AuthenticationProcessedAlreadyViewStateKey] = value; } - } - - /// <summary> - /// Allows an OpenID extension to read data out of an unverified positive authentication assertion - /// and send it down to the client browser so that Javascript running on the page can perform - /// some preprocessing on the extension data. - /// </summary> - /// <typeparam name="T">The extension <i>response</i> type that will read data from the assertion.</typeparam> - /// <param name="propertyName">The property name on the openid_identifier input box object that will be used to store the extension data. For example: sreg</param> - /// <remarks> - /// This method should be called from the <see cref="UnconfirmedPositiveAssertion"/> event handler. - /// </remarks> - [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "By design")] - public void RegisterClientScriptExtension<T>(string propertyName) where T : IClientScriptExtensionResponse { - Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(propertyName)); - this.RelyingParty.RegisterClientScriptExtension<T>(propertyName); - } - - #region ICallbackEventHandler Members - - /// <summary> - /// Returns the result of discovery on some Identifier passed to <see cref="ICallbackEventHandler.RaiseCallbackEvent"/>. - /// </summary> - /// <returns>The result of the callback.</returns> - /// <value>A whitespace delimited list of URLs that can be used to initiate authentication.</value> - string ICallbackEventHandler.GetCallbackResult() { - return this.GetCallbackResult(); - } - - /// <summary> - /// Performs discovery on some OpenID Identifier. Called directly from the user agent via - /// AJAX callback mechanisms. - /// </summary> - /// <param name="eventArgument">The identifier to perform discovery on.</param> - [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "We want to preserve the signature of the interface.")] - void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument) { - this.RaiseCallbackEvent(eventArgument); - } - - #endregion - - /// <summary> - /// Returns the results of a callback event that targets a control. - /// </summary> - /// <returns>The result of the callback.</returns> - [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "We want to preserve the signature of the interface.")] - protected virtual string GetCallbackResult() { - this.Page.Response.ContentType = "text/javascript"; - return this.discoveryResult; - } - - /// <summary> - /// Processes a callback event that targets a control. - /// </summary> - /// <param name="eventArgument">A string that represents an event argument to pass to the event handler.</param> - [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "We want to preserve the signature of the interface.")] - protected virtual void RaiseCallbackEvent(string eventArgument) { - string userSuppliedIdentifier = eventArgument; - - ErrorUtilities.VerifyNonZeroLength(userSuppliedIdentifier, "userSuppliedIdentifier"); - Logger.OpenId.InfoFormat("AJAX discovery on {0} requested.", userSuppliedIdentifier); - - this.Identifier = userSuppliedIdentifier; - - var serializer = new JavaScriptSerializer(); - IEnumerable<IAuthenticationRequest> requests = this.CreateRequests(this.Identifier); - this.discoveryResult = serializer.Serialize(this.AjaxRelyingParty.AsJsonDiscoveryResult(requests)); - } - - /// <summary> - /// Creates the relying party instance used to generate authentication requests. - /// </summary> - /// <param name="store">The store to pass to the relying party constructor.</param> - /// <returns>The instantiated relying party.</returns> - protected override OpenIdRelyingParty CreateRelyingParty(IOpenIdApplicationStore store) { - return new OpenIdAjaxRelyingParty(store); - } - - /// <summary> - /// Pre-discovers an identifier and makes the results available to the - /// user agent for javascript as soon as the page loads. - /// </summary> - /// <param name="identifier">The identifier.</param> - protected void PreloadDiscovery(Identifier identifier) { - this.PreloadDiscovery(new[] { identifier }); - } - - /// <summary> - /// Pre-discovers a given set of identifiers and makes the results available to the - /// user agent for javascript as soon as the page loads. - /// </summary> - /// <param name="identifiers">The identifiers to perform discovery on.</param> - protected void PreloadDiscovery(IEnumerable<Identifier> identifiers) { - string script = this.AjaxRelyingParty.AsAjaxPreloadedDiscoveryResult( - identifiers.SelectMany(id => this.CreateRequests(id))); - this.Page.ClientScript.RegisterClientScriptBlock(typeof(OpenIdRelyingPartyAjaxControlBase), this.ClientID, script, true); - } - - /// <summary> - /// Fires the <see cref="UnconfirmedPositiveAssertion"/> event. - /// </summary> - protected virtual void OnUnconfirmedPositiveAssertion() { - var unconfirmedPositiveAssertion = this.UnconfirmedPositiveAssertion; - if (unconfirmedPositiveAssertion != null) { - unconfirmedPositiveAssertion(this, null); - } - } - - /// <summary> - /// Raises the <see cref="E:Load"/> event. - /// </summary> - /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> - protected override void OnLoad(EventArgs e) { - base.OnLoad(e); - - // Our parent control ignores all OpenID messages included in a postback, - // but our AJAX controls hide an old OpenID message in a postback payload, - // so we deserialize it and process it when appropriate. - if (this.Page.IsPostBack) { - if (this.AuthenticationResponse != null && !this.AuthenticationProcessedAlready) { - // Only process messages targeted at this control. - // Note that Stateless mode causes no receiver to be indicated. - string receiver = this.AuthenticationResponse.GetUntrustedCallbackArgument(ReturnToReceivingControlId); - if (receiver == null || receiver == this.ClientID) { - this.ProcessResponse(this.AuthenticationResponse); - this.AuthenticationProcessedAlready = true; - } - } - } - } - - /// <summary> - /// Called when the <see cref="Identifier"/> property is changed. - /// </summary> - protected override void OnIdentifierChanged() { - base.OnIdentifierChanged(); - - // Since the identifier changed, make sure we reset any cached authentication on the user agent. - this.ViewState.Remove(AuthDataViewStateKey); - } - - /// <summary> - /// Raises the <see cref="E:System.Web.UI.Control.PreRender"/> event. - /// </summary> - /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param> - protected override void OnPreRender(EventArgs e) { - base.OnPreRender(e); - - this.SetWebAppPathOnUserAgent(); - this.Page.ClientScript.RegisterClientScriptResource(typeof(OpenIdRelyingPartyAjaxControlBase), EmbeddedAjaxJavascriptResource); - - StringBuilder initScript = new StringBuilder(); - - initScript.AppendLine(CallbackJSFunctionAsync + " = " + this.GetJsCallbackConvenienceFunction(true)); - initScript.AppendLine(CallbackJSFunction + " = " + this.GetJsCallbackConvenienceFunction(false)); - - // Positive assertions can last no longer than this library is willing to consider them valid, - // and when they come with OP private associations they last no longer than the OP is willing - // to consider them valid. We assume the OP will hold them valid for at least five minutes. - double assertionLifetimeInMilliseconds = Math.Min(TimeSpan.FromMinutes(5).TotalMilliseconds, Math.Min(OpenIdElement.Configuration.MaxAuthenticationTime.TotalMilliseconds, DotNetOpenAuthSection.Messaging.MaximumMessageLifetime.TotalMilliseconds)); - initScript.AppendLine(MaxPositiveAssertionLifetimeJsName + " = " + assertionLifetimeInMilliseconds.ToString(CultureInfo.InvariantCulture) + ";"); - - // We register this callback code explicitly with a specific type rather than the derived-type of the control - // to ensure that this discovery callback function is only set ONCE for the HTML document. - this.Page.ClientScript.RegisterClientScriptBlock(typeof(OpenIdRelyingPartyControlBase), "initializer", initScript.ToString(), true); - } - - /// <summary> - /// Sends server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object, which writes the content to be rendered on the client. - /// </summary> - /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param> - protected override void Render(HtmlTextWriter writer) { - Contract.Assume(writer != null, "Missing contract."); - base.Render(writer); - - // Emit a hidden field to let the javascript on the user agent know if an - // authentication has already successfully taken place. - string viewstateAuthData = this.ViewState[AuthDataViewStateKey] as string; - if (!string.IsNullOrEmpty(viewstateAuthData)) { - writer.AddAttribute(HtmlTextWriterAttribute.Name, this.OpenIdAuthDataFormKey); - writer.AddAttribute(HtmlTextWriterAttribute.Value, viewstateAuthData, true); - writer.AddAttribute(HtmlTextWriterAttribute.Type, "hidden"); - writer.RenderBeginTag(HtmlTextWriterTag.Input); - writer.RenderEndTag(); - } - } - - /// <summary> - /// Notifies the user agent via an AJAX response of a completed authentication attempt. - /// </summary> - protected override void ScriptClosingPopupOrIFrame() { - Action<AuthenticationStatus> callback = status => { - if (status == AuthenticationStatus.Authenticated) { - this.OnUnconfirmedPositiveAssertion(); // event handler will fill the clientScriptExtensions collection. - } - }; - - OutgoingWebResponse response = this.RelyingParty.ProcessResponseFromPopup( - this.RelyingParty.Channel.GetRequestFromContext(), - callback); - - response.Respond(); - } - - /// <summary> - /// Constructs a function that will initiate an AJAX callback. - /// </summary> - /// <param name="async">if set to <c>true</c> causes the AJAX callback to be a little more asynchronous. Note that <c>false</c> does not mean the call is absolutely synchronous.</param> - /// <returns>The string defining a javascript anonymous function that initiates a callback.</returns> - private string GetJsCallbackConvenienceFunction(bool async) { - string argumentParameterName = "argument"; - string callbackResultParameterName = "resultFunction"; - string callbackErrorCallbackParameterName = "errorCallback"; - string callback = Page.ClientScript.GetCallbackEventReference( - this, - argumentParameterName, - callbackResultParameterName, - argumentParameterName, - callbackErrorCallbackParameterName, - async); - return string.Format( - CultureInfo.InvariantCulture, - "function({1}, {2}, {3}) {{{0}\treturn {4};{0}}};", - Environment.NewLine, - argumentParameterName, - callbackResultParameterName, - callbackErrorCallbackParameterName, - callback); - } - - /// <summary> - /// Sets the window.aspnetapppath variable on the user agent so that cookies can be set with the proper path. - /// </summary> - private void SetWebAppPathOnUserAgent() { - string script = "window.aspnetapppath = " + MessagingUtilities.GetSafeJavascriptValue(this.Page.Request.ApplicationPath) + ";"; - this.Page.ClientScript.RegisterClientScriptBlock(typeof(OpenIdRelyingPartyAjaxControlBase), "webapppath", script, true); - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.js b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.js deleted file mode 100644 index 4de5188..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.js +++ /dev/null @@ -1,751 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdRelyingPartyAjaxControlBase.js" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// This file may be used and redistributed under the terms of the -// Microsoft Public License (Ms-PL) http://opensource.org/licenses/ms-pl.html -// </copyright> -//----------------------------------------------------------------------- - -if (window.dnoa_internal === undefined) { - window.dnoa_internal = {}; -} - -/// <summary>Removes a given element from the array.</summary> -/// <returns>True if the element was in the array, or false if it was not found.</returns> -Array.prototype.remove = function(element) { - function elementToRemoveLast(a, b) { - if (a == element) { return 1; } - if (b == element) { return -1; } - return 0; - } - this.sort(elementToRemoveLast); - if (this[this.length - 1] == element) { - this.pop(); - return true; - } else { - return false; - } -}; - -// Renders all the parameters in their string form, surrounded by parentheses. -window.dnoa_internal.argsToString = function() { - result = "("; - for (var i = 0; i < arguments.length; i++) { - if (i > 0) { result += ', '; } - var arg = arguments[i]; - if (typeof (arg) == 'string') { - arg = '"' + arg + '"'; - } else if (arg === null) { - arg = '[null]'; - } else if (arg === undefined) { - arg = '[undefined]'; - } - result += arg.toString(); - } - result += ')'; - return result; -}; - -window.dnoa_internal.registerEvent = function(name) { - var filterOnApplicability = function(fn, domElement) { - /// <summary>Wraps a given function with a check so that the function only executes when a given element is still in the DOM.</summary> - return function() { - var args = Array.prototype.slice.call(arguments); - if (!domElement) { - // no element used as a basis of applicability indicates we always fire this callback. - fn.apply(null, args); - } else { - var elements = document.getElementsByTagName(domElement.tagName); - var isElementInDom = false; - for (var i = 0; i < elements.length; i++) { - if (elements[i] === domElement) { - isElementInDom = true; - break; - } - } - if (isElementInDom) { - fn.apply(null, args); - } - } - } - }; - - window.dnoa_internal[name + 'Listeners'] = []; - window.dnoa_internal['add' + name] = function(fn, whileDomElementApplicable) { window.dnoa_internal[name + 'Listeners'].push(filterOnApplicability(fn, whileDomElementApplicable)); }; - window.dnoa_internal['remove' + name] = function(fn) { window.dnoa_internal[name + 'Listeners'].remove(fn); }; - window.dnoa_internal['fire' + name] = function() { - var args = Array.prototype.slice.call(arguments); - trace('Firing event ' + name + window.dnoa_internal.argsToString.apply(null, args), 'blue'); - var listeners = window.dnoa_internal[name + 'Listeners']; - for (var i = 0; i < listeners.length; i++) { - listeners[i].apply(null, args); - } - }; -}; - -window.dnoa_internal.registerEvent('DiscoveryStarted'); // (identifier) - fired when a discovery callback is ACTUALLY made to the RP -window.dnoa_internal.registerEvent('DiscoverySuccess'); // (identifier, discoveryResult, { fresh: true|false }) - fired after a discovery callback is returned from the RP successfully or a cached result is retrieved -window.dnoa_internal.registerEvent('DiscoveryFailed'); // (identifier, message) - fired after a discovery callback fails -window.dnoa_internal.registerEvent('AuthStarted'); // (discoveryResult, serviceEndpoint, { background: true|false }) -window.dnoa_internal.registerEvent('AuthFailed'); // (discoveryResult, serviceEndpoint, { background: true|false }) - fired for each individual ServiceEndpoint, and once at last with serviceEndpoint==null if all failed -window.dnoa_internal.registerEvent('AuthSuccess'); // (discoveryResult, serviceEndpoint, extensionResponses, { background: true|false, deserialized: true|false }) -window.dnoa_internal.registerEvent('AuthCleared'); // (discoveryResult, serviceEndpoint) - -window.dnoa_internal.discoveryResults = []; // user supplied identifiers and discovery results -window.dnoa_internal.discoveryInProgress = []; // identifiers currently being discovered and their callbacks - -// The possible authentication results -window.dnoa_internal.authSuccess = 'auth-success'; -window.dnoa_internal.authRefused = 'auth-refused'; -window.dnoa_internal.timedOut = 'timed-out'; - -/// <summary>Instantiates a new FrameManager.</summary> -/// <param name="maxFrames">The maximum number of concurrent 'jobs' (authentication attempts).</param> -window.dnoa_internal.FrameManager = function(maxFrames) { - this.queuedWork = []; - this.frames = []; - this.maxFrames = maxFrames; - - /// <summary>Called to queue up some work that will use an iframe as soon as it is available.</summary> - /// <param name="job"> - /// A delegate that must return { url: /*to point the iframe to*/, onCanceled: /* callback */ } - /// Its first parameter is the iframe created to service the request. - /// It will only be called when the work actually begins. - /// </param> - /// <param name="p1">Arbitrary additional parameter to pass to the job.</param> - this.enqueueWork = function(job, p1) { - // Assign an iframe to this task immediately if there is one available. - if (this.frames.length < this.maxFrames) { - this.createIFrame(job, p1); - } else { - this.queuedWork.unshift({ job: job, p1: p1 }); - } - }; - - /// <summary>Clears the job queue and immediately closes all iframes.</summary> - this.cancelAllWork = function() { - trace('Canceling all open and pending iframes.'); - while (this.queuedWork.pop()) { } - this.closeFrames(); - }; - - /// <summary>An event fired when a frame is closing.</summary> - this.onJobCompleted = function() { - // If there is a job in the queue, go ahead and start it up. - if (jobDesc = this.queuedWork.pop()) { - this.createIFrame(jobDesc.job, jobDesc.p1); - } - }; - - this.createIFrame = function(job, p1) { - var iframe = document.createElement("iframe"); - if (!window.openid_visible_iframe) { - iframe.setAttribute("width", 0); - iframe.setAttribute("height", 0); - iframe.setAttribute("style", "display: none"); - } - var jobDescription = job(iframe, p1); - iframe.setAttribute("src", jobDescription.url); - iframe.onCanceled = jobDescription.onCanceled; - iframe.dnoa_internal = window.dnoa_internal; - document.body.insertBefore(iframe, document.body.firstChild); - this.frames.push(iframe); - return iframe; - }; - - this.closeFrames = function() { - if (this.frames.length === 0) { return false; } - for (var i = 0; i < this.frames.length; i++) { - this.frames[i].src = "about:blank"; // doesn't have to exist. Just stop its processing. - if (this.frames[i].parentNode) { this.frames[i].parentNode.removeChild(this.frames[i]); } - } - while (this.frames.length > 0) { - var frame = this.frames.pop(); - if (frame.onCanceled) { frame.onCanceled(); } - } - return true; - }; - - this.closeFrame = function(frame) { - frame.src = "about:blank"; // doesn't have to exist. Just stop its processing. - if (frame.parentNode) { frame.parentNode.removeChild(frame); } - var removed = this.frames.remove(frame); - this.onJobCompleted(); - return removed; - }; -}; - -/// <summary>Instantiates an object that represents an OpenID Identifier.</summary> -window.OpenIdIdentifier = function(identifier) { - if (!identifier || identifier.length === 0) { - throw 'Error: trying to create OpenIdIdentifier for null or empty string.'; - } - - /// <summary>Performs discovery on the identifier.</summary> - /// <param name="onDiscoverSuccess">A function(DiscoveryResult) callback to be called when discovery has completed successfully.</param> - /// <param name="onDiscoverFailure">A function callback to be called when discovery has completed in failure.</param> - this.discover = function(onDiscoverSuccess, onDiscoverFailure) { - /// <summary>Receives the results of a successful discovery (even if it yielded 0 results).</summary> - function discoverSuccessCallback(discoveryResult, identifier) { - trace('Discovery completed for: ' + identifier); - - // Deserialize the JSON object and store the result if it was a successful discovery. - discoveryResult = eval('(' + discoveryResult + ')'); - - // Add behavior for later use. - discoveryResult = new window.dnoa_internal.DiscoveryResult(identifier, discoveryResult); - window.dnoa_internal.discoveryResults[identifier] = discoveryResult; - - window.dnoa_internal.fireDiscoverySuccess(identifier, discoveryResult, { fresh: true }); - - // Clear our "in discovery" state and fire callbacks - var callbacks = window.dnoa_internal.discoveryInProgress[identifier]; - window.dnoa_internal.discoveryInProgress[identifier] = null; - - if (callbacks) { - for (var i = 0; i < callbacks.onSuccess.length; i++) { - if (callbacks.onSuccess[i]) { - callbacks.onSuccess[i](discoveryResult); - } - } - } - } - - /// <summary>Receives the discovery failure notification.</summary> - function discoverFailureCallback(message, userSuppliedIdentifier) { - trace('Discovery failed for: ' + identifier); - - // Clear our "in discovery" state and fire callbacks - var callbacks = window.dnoa_internal.discoveryInProgress[identifier]; - window.dnoa_internal.discoveryInProgress[identifier] = null; - - if (callbacks) { - for (var i = 0; i < callbacks.onSuccess.length; i++) { - if (callbacks.onFailure[i]) { - callbacks.onFailure[i](message); - } - } - } - - window.dnoa_internal.fireDiscoveryFailed(identifier, message); - } - - if (window.dnoa_internal.discoveryResults[identifier]) { - trace("We've already discovered " + identifier + " so we're using the cached version."); - - // In this special case, we never fire the DiscoveryStarted event. - window.dnoa_internal.fireDiscoverySuccess(identifier, window.dnoa_internal.discoveryResults[identifier], { fresh: false }); - - if (onDiscoverSuccess) { - onDiscoverSuccess(window.dnoa_internal.discoveryResults[identifier]); - } - - return; - } - - window.dnoa_internal.fireDiscoveryStarted(identifier); - - if (!window.dnoa_internal.discoveryInProgress[identifier]) { - trace('starting discovery on ' + identifier); - window.dnoa_internal.discoveryInProgress[identifier] = { - onSuccess: [onDiscoverSuccess], - onFailure: [onDiscoverFailure] - }; - window.dnoa_internal.callbackAsync(identifier, discoverSuccessCallback, discoverFailureCallback); - } else { - trace('Discovery on ' + identifier + ' already started. Registering an additional callback.'); - window.dnoa_internal.discoveryInProgress[identifier].onSuccess.push(onDiscoverSuccess); - window.dnoa_internal.discoveryInProgress[identifier].onFailure.push(onDiscoverFailure); - } - }; - - /// <summary>Performs discovery and immediately begins checkid_setup to authenticate the user using a given identifier.</summary> - this.login = function(onSuccess, onLoginFailure) { - this.discover(function(discoveryResult) { - if (discoveryResult) { - trace('Discovery succeeded and found ' + discoveryResult.length + ' OpenID service endpoints.'); - if (discoveryResult.length > 0) { - discoveryResult[0].loginPopup(onSuccess, onLoginFailure); - } else { - trace("This doesn't look like an OpenID Identifier. Aborting login."); - if (onLoginFailure) { - onLoginFailure(); - } - } - } - }); - }; - - /// <summary>Performs discovery and immediately begins checkid_immediate on all discovered endpoints.</summary> - this.loginBackground = function(frameManager, onLoginSuccess, onLoginFailure, timeout, onLoginLastFailure) { - this.discover(function(discoveryResult) { - if (discoveryResult) { - trace('Discovery succeeded and found ' + discoveryResult.length + ' OpenID service endpoints.'); - if (discoveryResult.length > 0) { - discoveryResult.loginBackground(frameManager, onLoginSuccess, onLoginFailure, onLoginLastFailure || onLoginFailure, timeout); - } else { - trace("This doesn't look like an OpenID Identifier. Aborting login."); - if (onLoginFailure) { - onLoginFailure(); - } - } - } - }); - }; - - this.toString = function() { - return identifier; - }; -}; - -/// <summary>Invoked by RP web server when an authentication has completed.</summary> -/// <remarks>The duty of this method is to distribute the notification to the appropriate tracking object.</remarks> -window.dnoa_internal.processAuthorizationResult = function(resultUrl, extensionResponses) { - //trace('processAuthorizationResult ' + resultUrl); - var resultUri = new window.dnoa_internal.Uri(resultUrl); - trace('processing auth result with extensionResponses: ' + extensionResponses); - if (extensionResponses) { - extensionResponses = eval(extensionResponses); - } - - // Find the tracking object responsible for this request. - var userSuppliedIdentifier = resultUri.getQueryArgValue('dnoa.userSuppliedIdentifier'); - if (!userSuppliedIdentifier) { - throw 'processAuthorizationResult called but no userSuppliedIdentifier parameter was found. Exiting function.'; - } - var discoveryResult = window.dnoa_internal.discoveryResults[userSuppliedIdentifier]; - if (!discoveryResult) { - throw 'processAuthorizationResult called but no discovery result matching user supplied identifier ' + userSuppliedIdentifier + ' was found. Exiting function.'; - } - - var opEndpoint = resultUri.getQueryArgValue("openid.op_endpoint") ? resultUri.getQueryArgValue("openid.op_endpoint") : resultUri.getQueryArgValue("dnoa.op_endpoint"); - var respondingEndpoint = discoveryResult.findByEndpoint(opEndpoint); - trace('Auth result for ' + respondingEndpoint.host + ' received.'); //: ' + resultUrl); - - if (window.dnoa_internal.isAuthSuccessful(resultUri)) { - discoveryResult.successAuthData = resultUrl; - respondingEndpoint.onAuthSuccess(resultUri, extensionResponses); - - var parsedPositiveAssertion = new window.dnoa_internal.PositiveAssertion(resultUri); - if (parsedPositiveAssertion.claimedIdentifier && parsedPositiveAssertion.claimedIdentifier != discoveryResult.claimedIdentifier) { - discoveryResult.claimedIdentifier = parsedPositiveAssertion.claimedIdentifier; - trace('Authenticated as ' + parsedPositiveAssertion.claimedIdentifier); - } - } else { - respondingEndpoint.onAuthFailed(); - } -}; - -window.dnoa_internal.isAuthSuccessful = function(resultUri) { - if (window.dnoa_internal.isOpenID2Response(resultUri)) { - return resultUri.getQueryArgValue("openid.mode") == "id_res"; - } else { - return resultUri.getQueryArgValue("openid.mode") == "id_res" && !resultUri.containsQueryArg("openid.user_setup_url"); - } -}; - -window.dnoa_internal.isOpenID2Response = function(resultUri) { - return resultUri.containsQueryArg("openid.ns"); -}; - -/// <summary>Instantiates an object that stores discovery results of some identifier.</summary> -window.dnoa_internal.DiscoveryResult = function(identifier, discoveryInfo) { - var thisDiscoveryResult = this; - - /// <summary> - /// Instantiates an object that describes an OpenID service endpoint and facilitates - /// initiating and tracking an authentication request. - /// </summary> - function ServiceEndpoint(requestInfo, userSuppliedIdentifier) { - this.immediate = requestInfo.immediate ? new window.dnoa_internal.Uri(requestInfo.immediate) : null; - this.setup = requestInfo.setup ? new window.dnoa_internal.Uri(requestInfo.setup) : null; - this.endpoint = new window.dnoa_internal.Uri(requestInfo.endpoint); - this.host = this.endpoint.getHost(); - this.userSuppliedIdentifier = userSuppliedIdentifier; - var thisServiceEndpoint = this; // closure so that delegates have the right instance - this.loginPopup = function(onAuthSuccess, onAuthFailed) { - thisServiceEndpoint.abort(); // ensure no concurrent attempts - window.dnoa_internal.fireAuthStarted(thisDiscoveryResult, thisServiceEndpoint, { background: false }); - thisDiscoveryResult.onAuthSuccess = onAuthSuccess; - thisDiscoveryResult.onAuthFailed = onAuthFailed; - var chromeHeight = 55; // estimated height of browser title bar and location bar - var bottomMargin = 45; // estimated bottom space on screen likely to include a task bar - var width = 1000; - var height = 600; - if (thisServiceEndpoint.setup.getQueryArgValue("openid.return_to").indexOf("dnoa.popupUISupported") >= 0) { - trace('This OP supports the UI extension. Using smaller window size.'); - width = 500; // spec calls for 450px, but Yahoo needs 500px - height = 500; - } else { - trace("This OP doesn't appear to support the UI extension. Using larger window size."); - } - - var left = (screen.width - width) / 2; - var top = (screen.height - bottomMargin - height - chromeHeight) / 2; - thisServiceEndpoint.popup = window.open(thisServiceEndpoint.setup, 'opLogin', 'status=0,toolbar=0,location=1,resizable=1,scrollbars=1,left=' + left + ',top=' + top + ',width=' + width + ',height=' + height); - - // If the OP supports the UI extension it MAY close its own window - // for a negative assertion. We must be able to recover from that scenario. - var thisServiceEndpointLocal = thisServiceEndpoint; - thisServiceEndpoint.popupCloseChecker = window.setInterval(function() { - if (thisServiceEndpointLocal.popup) { - try { - if (thisServiceEndpointLocal.popup.closed) { - // The window closed, either because the user closed it, canceled at the OP, - // or approved at the OP and the popup window closed itself due to our script. - // If we were graying out the entire page while the child window was up, - // we would probably revert that here. - window.clearInterval(thisServiceEndpointLocal.popupCloseChecker); - thisServiceEndpointLocal.popup = null; - - // The popup may have managed to inform us of the result already, - // so check whether the callback method was cleared already, which - // would indicate we've already processed this. - if (window.dnoa_internal.processAuthorizationResult) { - trace('User or OP canceled by closing the window.'); - window.dnoa_internal.fireAuthFailed(thisDiscoveryResult, thisServiceEndpoint, { background: false }); - if (thisDiscoveryResult.onAuthFailed) { - thisDiscoveryResult.onAuthFailed(thisDiscoveryResult, thisServiceEndpoint); - } - } - } - } catch (e) { - // This usually happens because the popup is currently displaying the OP's - // page from another domain, which makes the popup temporarily off limits to us. - // Just skip this interval and wait for the next callback. - } - } else { - // if there's no popup, there's no reason to keep this timer up. - window.clearInterval(thisServiceEndpointLocal.popupCloseChecker); - } - }, 250); - }; - - this.loginBackgroundJob = function(iframe, timeout) { - thisServiceEndpoint.abort(); // ensure no concurrent attempts - if (timeout) { - thisServiceEndpoint.timeout = setTimeout(function() { thisServiceEndpoint.onAuthenticationTimedOut(); }, timeout); - } - window.dnoa_internal.fireAuthStarted(thisDiscoveryResult, thisServiceEndpoint, { background: true }); - trace('iframe hosting ' + thisServiceEndpoint.endpoint + ' now OPENING (timeout ' + timeout + ').'); - //trace('initiating auth attempt with: ' + thisServiceEndpoint.immediate); - thisServiceEndpoint.iframe = iframe; - return { - url: thisServiceEndpoint.immediate.toString(), - onCanceled: function() { - thisServiceEndpoint.abort(); - window.dnoa_internal.fireAuthFailed(thisDiscoveryResult, thisServiceEndpoint, { background: true }); - } - }; - }; - - this.busy = function() { - return thisServiceEndpoint.iframe || thisServiceEndpoint.popup; - }; - - this.completeAttempt = function(successful) { - if (!thisServiceEndpoint.busy()) { return false; } - window.clearInterval(thisServiceEndpoint.timeout); - var background = thisServiceEndpoint.iframe !== null; - if (thisServiceEndpoint.iframe) { - trace('iframe hosting ' + thisServiceEndpoint.endpoint + ' now CLOSING.'); - thisDiscoveryResult.frameManager.closeFrame(thisServiceEndpoint.iframe); - thisServiceEndpoint.iframe = null; - } - if (thisServiceEndpoint.popup) { - thisServiceEndpoint.popup.close(); - thisServiceEndpoint.popup = null; - } - if (thisServiceEndpoint.timeout) { - window.clearTimeout(thisServiceEndpoint.timeout); - thisServiceEndpoint.timeout = null; - } - - if (!successful && !thisDiscoveryResult.busy() && !thisDiscoveryResult.findSuccessfulRequest()) { - // fire the failed event with NO service endpoint indicating the entire auth attempt has failed. - window.dnoa_internal.fireAuthFailed(thisDiscoveryResult, null, { background: background }); - if (thisDiscoveryResult.onLastAttemptFailed) { - thisDiscoveryResult.onLastAttemptFailed(thisDiscoveryResult); - } - } - - return true; - }; - - this.onAuthenticationTimedOut = function() { - var background = thisServiceEndpoint.iframe !== null; - if (thisServiceEndpoint.completeAttempt()) { - trace(thisServiceEndpoint.host + " timed out"); - thisServiceEndpoint.result = window.dnoa_internal.timedOut; - } - window.dnoa_internal.fireAuthFailed(thisDiscoveryResult, thisServiceEndpoint, { background: background }); - }; - - this.onAuthSuccess = function(authUri, extensionResponses) { - var background = thisServiceEndpoint.iframe !== null; - if (thisServiceEndpoint.completeAttempt(true)) { - trace(thisServiceEndpoint.host + " authenticated!"); - thisServiceEndpoint.result = window.dnoa_internal.authSuccess; - thisServiceEndpoint.successReceived = new Date(); - thisServiceEndpoint.claimedIdentifier = authUri.getQueryArgValue('openid.claimed_id'); - thisServiceEndpoint.response = authUri; - thisServiceEndpoint.extensionResponses = extensionResponses; - thisDiscoveryResult.abortAll(); - if (thisDiscoveryResult.onAuthSuccess) { - thisDiscoveryResult.onAuthSuccess(thisDiscoveryResult, thisServiceEndpoint, extensionResponses); - } - window.dnoa_internal.fireAuthSuccess(thisDiscoveryResult, thisServiceEndpoint, extensionResponses, { background: background }); - } - }; - - this.onAuthFailed = function() { - var background = thisServiceEndpoint.iframe !== null; - if (thisServiceEndpoint.completeAttempt()) { - trace(thisServiceEndpoint.host + " failed authentication"); - thisServiceEndpoint.result = window.dnoa_internal.authRefused; - window.dnoa_internal.fireAuthFailed(thisDiscoveryResult, thisServiceEndpoint, { background: background }); - if (thisDiscoveryResult.onAuthFailed) { - thisDiscoveryResult.onAuthFailed(thisDiscoveryResult, thisServiceEndpoint); - } - } - }; - - this.abort = function() { - if (thisServiceEndpoint.completeAttempt()) { - trace(thisServiceEndpoint.host + " aborted"); - // leave the result as whatever it was before. - } - }; - - this.clear = function() { - thisServiceEndpoint.result = null; - thisServiceEndpoint.extensionResponses = null; - thisServiceEndpoint.successReceived = null; - thisServiceEndpoint.claimedIdentifier = null; - thisServiceEndpoint.response = null; - if (this.onCleared) { - this.onCleared(thisServiceEndpoint, thisDiscoveryResult); - } - if (thisDiscoveryResult.onCleared) { - thisDiscoveryResult.onCleared(thisDiscoveryResult, thisServiceEndpoint); - } - window.dnoa_internal.fireAuthCleared(thisDiscoveryResult, thisServiceEndpoint); - }; - - this.toString = function() { - return "[ServiceEndpoint: " + thisServiceEndpoint.host + "]"; - }; - } - - this.cloneWithOneServiceEndpoint = function(serviceEndpoint) { - var clone = window.dnoa_internal.clone(this); - clone.userSuppliedIdentifier = serviceEndpoint.claimedIdentifier; - - // Erase all SEPs except the given one, and put it into first position. - clone.length = 1; - for (var i = 0; i < this.length; i++) { - if (clone[i].endpoint.toString() == serviceEndpoint.endpoint.toString()) { - var tmp = clone[i]; - clone[i] = null; - clone[0] = tmp; - } else { - clone[i] = null; - } - } - - return clone; - }; - - this.userSuppliedIdentifier = identifier; - this.error = discoveryInfo.error; - - if (discoveryInfo) { - this.claimedIdentifier = discoveryInfo.claimedIdentifier; // The claimed identifier may be null if the user provided an OP Identifier. - this.length = discoveryInfo.requests.length; - for (var i = 0; i < discoveryInfo.requests.length; i++) { - this[i] = new ServiceEndpoint(discoveryInfo.requests[i], identifier); - } - } else { - this.length = 0; - } - - if (this.length === 0) { - trace('Discovery completed, but yielded no service endpoints.'); - } else { - trace('Discovered claimed identifier: ' + (this.claimedIdentifier ? this.claimedIdentifier : "(directed identity)")); - } - - // Add extra tracking bits and behaviors. - this.findByEndpoint = function(opEndpoint) { - for (var i = 0; i < thisDiscoveryResult.length; i++) { - if (thisDiscoveryResult[i].endpoint == opEndpoint) { - return thisDiscoveryResult[i]; - } - } - }; - - this.busy = function() { - for (var i = 0; i < thisDiscoveryResult.length; i++) { - if (thisDiscoveryResult[i].busy()) { - return true; - } - } - }; - - // Add extra tracking bits and behaviors. - this.findSuccessfulRequest = function() { - for (var i = 0; i < thisDiscoveryResult.length; i++) { - if (thisDiscoveryResult[i].result === window.dnoa_internal.authSuccess) { - return thisDiscoveryResult[i]; - } - } - }; - - this.abortAll = function() { - if (thisDiscoveryResult.frameManager) { - // Abort all other asynchronous authentication attempts that may be in progress - // for this particular claimed identifier. - thisDiscoveryResult.frameManager.cancelAllWork(); - for (var i = 0; i < thisDiscoveryResult.length; i++) { - thisDiscoveryResult[i].abort(); - } - } else { - trace('abortAll called without a frameManager being previously set.'); - } - }; - - /// <summary>Initiates an asynchronous checkid_immediate login attempt against all possible service endpoints for an Identifier.</summary> - /// <param name="frameManager">The work queue for authentication iframes.</param> - /// <param name="onAuthSuccess">Fired when an endpoint responds affirmatively.</param> - /// <param name="onAuthFailed">Fired when an endpoint responds negatively.</param> - /// <param name="onLastAuthFailed">Fired when all authentication attempts have responded negatively or timed out.</param> - /// <param name="timeout">Timeout for an individual service endpoint to respond before the iframe closes.</param> - this.loginBackground = function(frameManager, onAuthSuccess, onAuthFailed, onLastAuthFailed, timeout) { - if (!frameManager) { - throw "No frameManager specified."; - } - var priorSuccessRespondingEndpoint = thisDiscoveryResult.findSuccessfulRequest(); - if (priorSuccessRespondingEndpoint) { - // In this particular case, we do not fire an AuthStarted event. - window.dnoa_internal.fireAuthSuccess(thisDiscoveryResult, priorSuccessRespondingEndpoint, priorSuccessRespondingEndpoint.extensionResponses, { background: true }); - if (onAuthSuccess) { - onAuthSuccess(thisDiscoveryResult, priorSuccessRespondingEndpoint); - } - } else { - if (thisDiscoveryResult.busy()) { - trace('Warning: DiscoveryResult.loginBackground invoked while a login attempt is already in progress. Discarding second login request.', 'red'); - return; - } - thisDiscoveryResult.frameManager = frameManager; - thisDiscoveryResult.onAuthSuccess = onAuthSuccess; - thisDiscoveryResult.onAuthFailed = onAuthFailed; - thisDiscoveryResult.onLastAttemptFailed = onLastAuthFailed; - // Notify listeners that general authentication is beginning. Individual ServiceEndpoints - // will fire their own events as each of them begin their iframe 'job'. - window.dnoa_internal.fireAuthStarted(thisDiscoveryResult, null, { background: true }); - if (thisDiscoveryResult.length > 0) { - for (var i = 0; i < thisDiscoveryResult.length; i++) { - thisDiscoveryResult.frameManager.enqueueWork(thisDiscoveryResult[i].loginBackgroundJob, timeout); - } - } - } - }; - - this.toString = function() { - return "[DiscoveryResult: " + thisDiscoveryResult.userSuppliedIdentifier + "]"; - }; -}; - -/// <summary> -/// Called in a page had an AJAX control that had already obtained a positive assertion -/// when a postback occurred, and now that control wants to restore its 'authenticated' state. -/// </summary> -/// <param name="positiveAssertion">The string form of the URI that contains the positive assertion.</param> -window.dnoa_internal.deserializePreviousAuthentication = function(positiveAssertion) { - if (!positiveAssertion || positiveAssertion.length === 0) { - return; - } - - trace('Revitalizing an old positive assertion from a prior postback.'); - - // The control ensures that we ALWAYS have an OpenID 2.0-style claimed_id attribute, even against - // 1.0 Providers via the return_to URL mechanism. - var parsedPositiveAssertion = new window.dnoa_internal.PositiveAssertion(positiveAssertion); - - // We weren't given a full discovery history, but we can spoof this much from the - // authentication assertion. - trace('Deserialized claimed_id: ' + parsedPositiveAssertion.claimedIdentifier + ' and endpoint: ' + parsedPositiveAssertion.endpoint); - var discoveryInfo = { - claimedIdentifier: parsedPositiveAssertion.claimedIdentifier, - requests: [{ endpoint: parsedPositiveAssertion.endpoint}] - }; - - discoveryResult = new window.dnoa_internal.DiscoveryResult(parsedPositiveAssertion.userSuppliedIdentifier, discoveryInfo); - window.dnoa_internal.discoveryResults[parsedPositiveAssertion.userSuppliedIdentifier] = discoveryResult; - discoveryResult[0].result = window.dnoa_internal.authSuccess; - discoveryResult.successAuthData = positiveAssertion; - - // restore old state from before postback - window.dnoa_internal.fireAuthSuccess(discoveryResult, discoveryResult[0], null, { background: true, deserialized: true }); -}; - -window.dnoa_internal.PositiveAssertion = function(uri) { - uri = new window.dnoa_internal.Uri(uri.toString()); - this.endpoint = new window.dnoa_internal.Uri(uri.getQueryArgValue("dnoa.op_endpoint")); - this.userSuppliedIdentifier = uri.getQueryArgValue('dnoa.userSuppliedIdentifier'); - this.claimedIdentifier = uri.getQueryArgValue('openid.claimed_id'); - if (!this.claimedIdentifier) { - this.claimedIdentifier = uri.getQueryArgValue('dnoa.claimed_id'); - } - this.toString = function() { return uri.toString(); }; -}; - -window.dnoa_internal.clone = function(obj) { - if (obj === null || typeof (obj) != 'object' || !isNaN(obj)) { // !isNaN catches Date objects - return obj; - } - - var temp = {}; - for (var key in obj) { - temp[key] = window.dnoa_internal.clone(obj[key]); - } - - // Copy over some built-in methods that were not included in the above loop, - // but nevertheless may have been overridden. - temp.toString = window.dnoa_internal.clone(obj.toString); - - return temp; -}; - -// Deserialized the preloaded discovery results -window.dnoa_internal.loadPreloadedDiscoveryResults = function(preloadedDiscoveryResults) { - trace('found ' + preloadedDiscoveryResults.length + ' preloaded discovery results.'); - for (var i = 0; i < preloadedDiscoveryResults.length; i++) { - var result = preloadedDiscoveryResults[i]; - if (!window.dnoa_internal.discoveryResults[result.userSuppliedIdentifier]) { - window.dnoa_internal.discoveryResults[result.userSuppliedIdentifier] = new window.dnoa_internal.DiscoveryResult(result.userSuppliedIdentifier, result.discoveryResult); - trace('Preloaded discovery on: ' + window.dnoa_internal.discoveryResults[result.userSuppliedIdentifier].userSuppliedIdentifier); - } else { - trace('Skipped preloaded discovery on: ' + window.dnoa_internal.discoveryResults[result.userSuppliedIdentifier].userSuppliedIdentifier + ' because we have a cached discovery result on it.'); - } - } -}; - -window.dnoa_internal.clearExpiredPositiveAssertions = function() { - for (identifier in window.dnoa_internal.discoveryResults) { - var discoveryResult = window.dnoa_internal.discoveryResults[identifier]; - if (typeof (discoveryResult) != 'object') { continue; } // skip functions - for (var i = 0; i < discoveryResult.length; i++) { - if (discoveryResult[i] && discoveryResult[i].result === window.dnoa_internal.authSuccess) { - if (new Date() - discoveryResult[i].successReceived > window.dnoa_internal.maxPositiveAssertionLifetime) { - // This positive assertion is too old, and may eventually be rejected by DNOA during verification. - // Let's clear out the positive assertion so it can be renewed. - trace('Clearing out expired positive assertion from ' + discoveryResult[i].host); - discoveryResult[i].clear(); - } - } - } - } -}; - -window.setInterval(window.dnoa_internal.clearExpiredPositiveAssertions, 1000); diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs deleted file mode 100644 index 16ea839..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs +++ /dev/null @@ -1,1054 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdRelyingPartyControlBase.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -[assembly: System.Web.UI.WebResource(DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyControlBase.EmbeddedJavascriptResource, "text/javascript")] - -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; - using System.Drawing.Design; - using System.Globalization; - using System.Linq; - using System.Text; - using System.Text.RegularExpressions; - using System.Web; - using System.Web.Security; - using System.Web.UI; - using DotNetOpenAuth.ComponentModel; - using DotNetOpenAuth.Configuration; - 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. - /// </summary> - [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "OnSite", Justification = "Two words intended.")] - public enum LogOnSiteNotification { - /// <summary> - /// The rest of the web site is unaware that the user just completed an OpenID login. - /// </summary> - None, - - /// <summary> - /// After the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event is fired - /// the control automatically calls <see cref="System.Web.Security.FormsAuthentication.RedirectFromLoginPage(string, bool)"/> - /// with the <see cref="IAuthenticationResponse.ClaimedIdentifier"/> as the username - /// unless the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event handler sets - /// <see cref="OpenIdEventArgs.Cancel"/> property to true. - /// </summary> - FormsAuthentication, - } - - /// <summary> - /// How an OpenID user session should be persisted across visits. - /// </summary> - public enum LogOnPersistence { - /// <summary> - /// The user should only be logged in as long as the browser window remains open. - /// Nothing is persisted to help the user on a return visit. Public kiosk mode. - /// </summary> - Session, - - /// <summary> - /// The user should only be logged in as long as the browser window remains open. - /// The OpenID Identifier is persisted to help expedite re-authentication when - /// the user visits the next time. - /// </summary> - SessionAndPersistentIdentifier, - - /// <summary> - /// The user is issued a persistent authentication ticket so that no login is - /// necessary on their return visit. - /// </summary> - PersistentAuthentication, - } - - /// <summary> - /// A common base class for OpenID Relying Party controls. - /// </summary> - [DefaultProperty("Identifier"), ValidationProperty("Identifier")] - [ParseChildren(true), PersistChildren(false)] - public abstract class OpenIdRelyingPartyControlBase : Control, IPostBackEventHandler, IDisposable { - /// <summary> - /// The manifest resource name of the javascript file to include on the hosting page. - /// </summary> - internal const string EmbeddedJavascriptResource = Util.DefaultNamespace + ".OpenId.RelyingParty.OpenIdRelyingPartyControlBase.js"; - - /// <summary> - /// The cookie used to persist the Identifier the user logged in with. - /// </summary> - internal const string PersistentIdentifierCookieName = OpenIdUtilities.CustomParameterPrefix + "OpenIDIdentifier"; - - /// <summary> - /// The callback parameter name to use to store which control initiated the auth request. - /// </summary> - internal const string ReturnToReceivingControlId = OpenIdUtilities.CustomParameterPrefix + "receiver"; - - #region Protected internal callback parameter names - - /// <summary> - /// The callback parameter to use for recognizing when the callback is in a popup window or hidden iframe. - /// </summary> - protected internal const string UIPopupCallbackKey = OpenIdUtilities.CustomParameterPrefix + "uipopup"; - - /// <summary> - /// The parameter name to include in the formulated auth request so that javascript can know whether - /// the OP advertises support for the UI extension. - /// </summary> - protected internal const string PopupUISupportedJSHint = OpenIdUtilities.CustomParameterPrefix + "popupUISupported"; - - #endregion - - #region Property category constants - - /// <summary> - /// The "Appearance" category for properties. - /// </summary> - protected const string AppearanceCategory = "Appearance"; - - /// <summary> - /// The "Behavior" category for properties. - /// </summary> - protected const string BehaviorCategory = "Behavior"; - - /// <summary> - /// The "OpenID" category for properties and events. - /// </summary> - protected const string OpenIdCategory = "OpenID"; - - #endregion - - #region Private callback parameter names - - /// <summary> - /// The callback parameter for use with persisting the <see cref="UsePersistentCookie"/> property. - /// </summary> - private const string UsePersistentCookieCallbackKey = OpenIdUtilities.CustomParameterPrefix + "UsePersistentCookie"; - - /// <summary> - /// The callback parameter to use for recognizing when the callback is in the parent window. - /// </summary> - private const string UIPopupCallbackParentKey = OpenIdUtilities.CustomParameterPrefix + "uipopupParent"; - - #endregion - - #region Property default values - - /// <summary> - /// The default value for the <see cref="Stateless"/> property. - /// </summary> - private const bool StatelessDefault = false; - - /// <summary> - /// The default value for the <see cref="ReturnToUrl"/> property. - /// </summary> - private const string ReturnToUrlDefault = ""; - - /// <summary> - /// Default value of <see cref="UsePersistentCookie"/>. - /// </summary> - private const LogOnPersistence UsePersistentCookieDefault = LogOnPersistence.Session; - - /// <summary> - /// Default value of <see cref="LogOnMode"/>. - /// </summary> - private const LogOnSiteNotification LogOnModeDefault = LogOnSiteNotification.FormsAuthentication; - - /// <summary> - /// The default value for the <see cref="RealmUrl"/> property. - /// </summary> - private const string RealmUrlDefault = "~/"; - - /// <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="RequireSsl"/> property. - /// </summary> - private const bool RequireSslDefault = false; - - #endregion - - #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"; - - /// <summary> - /// The viewstate key to use for the <see cref="UsePersistentCookie"/> property. - /// </summary> - private const string UsePersistentCookieViewStateKey = "UsePersistentCookie"; - - /// <summary> - /// The viewstate key to use for the <see cref="LogOnMode"/> property. - /// </summary> - private const string LogOnModeViewStateKey = "LogOnMode"; - - /// <summary> - /// The viewstate key to use for the <see cref="RealmUrl"/> property. - /// </summary> - private const string RealmUrlViewStateKey = "RealmUrl"; - - /// <summary> - /// The viewstate key to use for the <see cref="ReturnToUrl"/> property. - /// </summary> - private const string ReturnToUrlViewStateKey = "ReturnToUrl"; - - /// <summary> - /// The key under which the value for the <see cref="Identifier"/> property will be stored. - /// </summary> - private const string IdentifierViewStateKey = "Identifier"; - - /// <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="RequireSsl"/> property. - /// </summary> - private const string RequireSslViewStateKey = "RequireSsl"; - - #endregion - - /// <summary> - /// The lifetime of the cookie used to persist the Identifier the user logged in with. - /// </summary> - private static readonly TimeSpan PersistentIdentifierTimeToLiveDefault = TimeSpan.FromDays(14); - - /// <summary> - /// Backing field for the <see cref="RelyingParty"/> property. - /// </summary> - private OpenIdRelyingParty relyingParty; - - /// <summary> - /// A value indicating whether the <see cref="relyingParty"/> field contains - /// an instance that we own and should Dispose. - /// </summary> - private bool relyingPartyOwned; - - /// <summary> - /// Initializes a new instance of the <see cref="OpenIdRelyingPartyControlBase"/> class. - /// </summary> - protected OpenIdRelyingPartyControlBase() { - Reporting.RecordFeatureUse(this); - } - - #region Events - - /// <summary> - /// Fired when the user has typed in their identifier, discovery was successful - /// and a login attempt is about to begin. - /// </summary> - [Description("Fired when the user has typed in their identifier, discovery was successful and a login attempt is about to begin."), Category(OpenIdCategory)] - public event EventHandler<OpenIdEventArgs> LoggingIn; - - /// <summary> - /// Fired upon completion of a successful login. - /// </summary> - [Description("Fired upon completion of a successful login."), Category(OpenIdCategory)] - public event EventHandler<OpenIdEventArgs> LoggedIn; - - /// <summary> - /// Fired when a login attempt fails. - /// </summary> - [Description("Fired when a login attempt fails."), Category(OpenIdCategory)] - public event EventHandler<OpenIdEventArgs> Failed; - - /// <summary> - /// Fired when an authentication attempt is canceled at the OpenID Provider. - /// </summary> - [Description("Fired when an authentication attempt is canceled at the OpenID Provider."), Category(OpenIdCategory)] - public event EventHandler<OpenIdEventArgs> Canceled; - - /// <summary> - /// Occurs when the <see cref="Identifier"/> property is changed. - /// </summary> - protected event EventHandler IdentifierChanged; - - #endregion - - /// <summary> - /// Gets or sets the <see cref="OpenIdRelyingParty"/> instance to use. - /// </summary> - /// <value>The default value is an <see cref="OpenIdRelyingParty"/> instance initialized according to the web.config file.</value> - /// <remarks> - /// A performance optimization would be to store off the - /// instance as a static member in your web site and set it - /// to this property in your <see cref="Control.Load">Page.Load</see> - /// event since instantiating these instances can be expensive on - /// heavily trafficked web pages. - /// </remarks> - [Browsable(false)] - public virtual OpenIdRelyingParty RelyingParty { - get { - if (this.relyingParty == null) { - this.relyingParty = this.CreateRelyingParty(); - this.ConfigureRelyingParty(this.relyingParty); - this.relyingPartyOwned = true; - } - return this.relyingParty; - } - - set { - if (this.relyingPartyOwned && this.relyingParty != null) { - this.relyingParty.Dispose(); - } - - this.relyingParty = value; - this.relyingPartyOwned = false; - } - } - - /// <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)] - [Description("Controls whether stateless mode is used.")] - public bool Stateless { - get { return (bool)(ViewState[StatelessViewStateKey] ?? StatelessDefault); } - set { ViewState[StatelessViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the OpenID <see cref="Realm"/> of the relying party web site. - /// </summary> - [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.Uri", Justification = "Using Uri.ctor for validation.")] - [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "DotNetOpenAuth.OpenId.Realm", Justification = "Using ctor for validation.")] - [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Bindable property must be simple type")] - [Bindable(true), DefaultValue(RealmUrlDefault), Category(OpenIdCategory)] - [Description("The OpenID Realm of the relying party web site.")] - [UrlProperty, Editor("System.Web.UI.Design.UrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))] - public string RealmUrl { - get { - return (string)(ViewState[RealmUrlViewStateKey] ?? RealmUrlDefault); - } - - set { - Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(value)); - - if (Page != null && !DesignMode) { - // Validate new value by trying to construct a Realm object based on it. - new Realm(OpenIdUtilities.GetResolvedRealm(this.Page, value, this.RelyingParty.Channel.GetRequestFromContext())); // throws an exception on failure. - } else { - // We can't fully test it, but it should start with either ~/ or a protocol. - if (Regex.IsMatch(value, @"^https?://")) { - new Uri(value.Replace("*.", string.Empty)); // make sure it's fully-qualified, but ignore wildcards - } else if (value.StartsWith("~/", StringComparison.Ordinal)) { - // this is valid too - } else { - throw new UriFormatException(); - } - } - ViewState[RealmUrlViewStateKey] = value; - } - } - - /// <summary> - /// Gets or sets the OpenID ReturnTo of the relying party web site. - /// </summary> - [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Bindable property must be simple type")] - [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.Uri", Justification = "Using Uri.ctor for validation.")] - [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Bindable property must be simple type")] - [Bindable(true), DefaultValue(ReturnToUrlDefault), Category(OpenIdCategory)] - [Description("The OpenID ReturnTo of the relying party web site.")] - [UrlProperty, Editor("System.Web.UI.Design.UrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))] - public string ReturnToUrl { - get { - return (string)(this.ViewState[ReturnToUrlViewStateKey] ?? ReturnToUrlDefault); - } - - set { - if (this.Page != null && !this.DesignMode) { - // Validate new value by trying to construct a Uri based on it. - new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.Page.ResolveUrl(value)); // throws an exception on failure. - } else { - // We can't fully test it, but it should start with either ~/ or a protocol. - if (Regex.IsMatch(value, @"^https?://")) { - new Uri(value); // make sure it's fully-qualified, but ignore wildcards - } else if (value.StartsWith("~/", StringComparison.Ordinal)) { - // this is valid too - } else { - throw new UriFormatException(); - } - } - - this.ViewState[ReturnToUrlViewStateKey] = value; - } - } - - /// <summary> - /// Gets or sets a value indicating whether to send a persistent cookie upon successful - /// login so the user does not have to log in upon returning to this site. - /// </summary> - [Bindable(true), DefaultValue(UsePersistentCookieDefault), Category(BehaviorCategory)] - [Description("Whether to send a persistent cookie upon successful " + - "login so the user does not have to log in upon returning to this site.")] - public virtual LogOnPersistence UsePersistentCookie { - get { return (LogOnPersistence)(this.ViewState[UsePersistentCookieViewStateKey] ?? UsePersistentCookieDefault); } - set { this.ViewState[UsePersistentCookieViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the way a completed login is communicated to the rest of the web site. - /// </summary> - [Bindable(true), DefaultValue(LogOnModeDefault), Category(BehaviorCategory)] - [Description("The way a completed login is communicated to the rest of the web site.")] - public virtual LogOnSiteNotification LogOnMode { - get { return (LogOnSiteNotification)(this.ViewState[LogOnModeViewStateKey] ?? LogOnModeDefault); } - set { this.ViewState[LogOnModeViewStateKey] = value; } - } - - /// <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 virtual PopupBehavior Popup { - get { return (PopupBehavior)(ViewState[PopupViewStateKey] ?? PopupDefault); } - set { ViewState[PopupViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets a value indicating whether to enforce on high security mode, - /// which requires the full authentication pipeline to be protected by SSL. - /// </summary> - [Bindable(true), DefaultValue(RequireSslDefault), Category(OpenIdCategory)] - [Description("Turns on high security mode, requiring the full authentication pipeline to be protected by SSL.")] - public bool RequireSsl { - get { return (bool)(ViewState[RequireSslViewStateKey] ?? RequireSslDefault); } - set { ViewState[RequireSslViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the Identifier that will be used to initiate login. - /// </summary> - [Bindable(true), Category(OpenIdCategory)] - [Description("The OpenID Identifier that this button will use to initiate login.")] - [TypeConverter(typeof(IdentifierConverter))] - public virtual Identifier Identifier { - get { - return (Identifier)ViewState[IdentifierViewStateKey]; - } - - set { - ViewState[IdentifierViewStateKey] = value; - this.OnIdentifierChanged(); - } - } - - /// <summary> - /// Gets or sets the default association preference to set on authentication requests. - /// </summary> - internal AssociationPreference AssociationPreference { get; set; } - - /// <summary> - /// Gets ancestor controls, starting with the immediate parent, and progressing to more distant ancestors. - /// </summary> - protected IEnumerable<Control> ParentControls { - get { - Control parent = this; - while ((parent = parent.Parent) != null) { - yield return parent; - } - } - } - - /// <summary> - /// Gets a value indicating whether this control is a child control of a composite OpenID control. - /// </summary> - /// <value> - /// <c>true</c> if this instance is embedded in parent OpenID control; otherwise, <c>false</c>. - /// </value> - protected bool IsEmbeddedInParentOpenIdControl { - get { return this.ParentControls.OfType<OpenIdRelyingPartyControlBase>().Any(); } - } - - /// <summary> - /// Clears any cookie set by this control to help the user on a returning visit next time. - /// </summary> - public static void LogOff() { - HttpContext.Current.Response.SetCookie(CreateIdentifierPersistingCookie(null)); - } - - /// <summary> - /// Immediately redirects to the OpenID Provider to verify the Identifier - /// provided in the text box. - /// </summary> - public void LogOn() { - IAuthenticationRequest request = this.CreateRequests().FirstOrDefault(); - ErrorUtilities.VerifyProtocol(request != null, OpenIdStrings.OpenIdEndpointNotFound); - this.LogOn(request); - } - - /// <summary> - /// Immediately redirects to the OpenID Provider to verify the Identifier - /// provided in the text box. - /// </summary> - /// <param name="request">The request.</param> - public void LogOn(IAuthenticationRequest request) { - Contract.Requires<ArgumentNullException>(request != null); - - if (this.IsPopupAppropriate(request)) { - this.ScriptPopupWindow(request); - } else { - request.RedirectToProvider(); - } - } - - #region IPostBackEventHandler Members - - /// <summary> - /// When implemented by a class, enables a server control to process an event raised when a form is posted to the server. - /// </summary> - /// <param name="eventArgument">A <see cref="T:System.String"/> that represents an optional event argument to be passed to the event handler.</param> - void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) { - this.RaisePostBackEvent(eventArgument); - } - - #endregion - - /// <summary> - /// Enables a server control to perform final clean up before it is released from memory. - /// </summary> - [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Unavoidable because base class does not expose a protected virtual Dispose(bool) method."), SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Base class doesn't implement virtual Dispose(bool), so we must call its Dispose() method.")] - public sealed override void Dispose() { - this.Dispose(true); - base.Dispose(); - GC.SuppressFinalize(this); - } - - /// <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> - protected internal virtual IEnumerable<IAuthenticationRequest> CreateRequests(Identifier identifier) { - Contract.Requires<ArgumentNullException>(identifier != null); - - // If this control is actually a member of another OpenID RP control, - // delegate creation of requests to the parent control. - var parentOwner = this.ParentControls.OfType<OpenIdRelyingPartyControlBase>().FirstOrDefault(); - if (parentOwner != null) { - return parentOwner.CreateRequests(identifier); - } else { - // Delegate to a private method to keep 'yield return' and Code Contract separate. - return this.CreateRequestsCore(identifier); - } - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources - /// </summary> - /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool disposing) { - if (disposing) { - if (this.relyingPartyOwned && this.relyingParty != null) { - this.relyingParty.Dispose(); - this.relyingParty = null; - } - } - } - - /// <summary> - /// When implemented by a class, enables a server control to process an event raised when a form is posted to the server. - /// </summary> - /// <param name="eventArgument">A <see cref="T:System.String"/> that represents an optional event argument to be passed to the event handler.</param> - [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "Predefined signature.")] - protected virtual void RaisePostBackEvent(string eventArgument) { - } - - /// <summary> - /// Creates the authentication requests for the value set in the <see cref="Identifier"/> property. - /// </summary> - /// <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> - protected IEnumerable<IAuthenticationRequest> CreateRequests() { - Contract.Requires<InvalidOperationException>(this.Identifier != null, OpenIdStrings.NoIdentifierSet); - return this.CreateRequests(this.Identifier); - } - - /// <summary> - /// Raises the <see cref="E:Load"/> event. - /// </summary> - /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> - protected override void OnLoad(EventArgs e) { - base.OnLoad(e); - - if (Page.IsPostBack) { - // OpenID responses NEVER come in the form of a postback. - return; - } - - if (this.Identifier == null) { - this.TryPresetIdentifierWithCookie(); - } - - // Take an unreliable sneek peek to see if we're in a popup and an OpenID - // assertion is coming in. We shouldn't process assertions in a popup window. - if (this.Page.Request.QueryString[UIPopupCallbackKey] == "1" && this.Page.Request.QueryString[UIPopupCallbackParentKey] == null) { - // We're in a popup window. We need to close it and pass the - // message back to the parent window for processing. - this.ScriptClosingPopupOrIFrame(); - return; // don't do any more processing on it now - } - - // Only sniff for an OpenID response if it is targeted at this control. - // Note that Stateless mode causes no receiver to be indicated, and - // we want to handle that, but only if there isn't a parent control that - // will be handling that. - string receiver = this.Page.Request.QueryString[ReturnToReceivingControlId] ?? this.Page.Request.Form[ReturnToReceivingControlId]; - if (receiver == this.ClientID || (receiver == null && !this.IsEmbeddedInParentOpenIdControl)) { - var response = this.RelyingParty.GetResponse(); - Logger.Controls.DebugFormat( - "The {0} control checked for an authentication response and found: {1}", - this.ID, - response != null ? response.Status.ToString() : "nothing"); - this.ProcessResponse(response); - } - } - - /// <summary> - /// Notifies the user agent via an AJAX response of a completed authentication attempt. - /// </summary> - protected virtual void ScriptClosingPopupOrIFrame() { - this.RelyingParty.ProcessResponseFromPopup(); - } - - /// <summary> - /// Called when the <see cref="Identifier"/> property is changed. - /// </summary> - protected virtual void OnIdentifierChanged() { - var identifierChanged = this.IdentifierChanged; - if (identifierChanged != null) { - identifierChanged(this, EventArgs.Empty); - } - } - - /// <summary> - /// Processes the response. - /// </summary> - /// <param name="response">The response.</param> - protected virtual void ProcessResponse(IAuthenticationResponse response) { - if (response == null) { - return; - } - string persistentString = response.GetUntrustedCallbackArgument(UsePersistentCookieCallbackKey); - if (persistentString != null) { - this.UsePersistentCookie = (LogOnPersistence)Enum.Parse(typeof(LogOnPersistence), persistentString); - } - - switch (response.Status) { - case AuthenticationStatus.Authenticated: - this.OnLoggedIn(response); - break; - case AuthenticationStatus.Canceled: - this.OnCanceled(response); - break; - case AuthenticationStatus.Failed: - this.OnFailed(response); - break; - case AuthenticationStatus.SetupRequired: - case AuthenticationStatus.ExtensionsOnly: - default: - // The NotApplicable (extension-only assertion) is NOT one that we support - // in this control because that scenario is primarily interesting to RPs - // that are asking a specific OP, and it is not user-initiated as this textbox - // is designed for. - throw new InvalidOperationException(MessagingStrings.UnexpectedMessageReceivedOfMany); - } - } - - /// <summary> - /// Raises the <see cref="E:System.Web.UI.Control.PreRender"/> event. - /// </summary> - /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param> - protected override void OnPreRender(EventArgs e) { - base.OnPreRender(e); - - this.Page.ClientScript.RegisterClientScriptResource(typeof(OpenIdRelyingPartyControlBase), EmbeddedJavascriptResource); - } - - /// <summary> - /// Fires the <see cref="LoggedIn"/> event. - /// </summary> - /// <param name="response">The response.</param> - protected virtual void OnLoggedIn(IAuthenticationResponse response) { - Contract.Requires<ArgumentNullException>(response != null); - Contract.Requires<ArgumentException>(response.Status == AuthenticationStatus.Authenticated); - - var loggedIn = this.LoggedIn; - OpenIdEventArgs args = new OpenIdEventArgs(response); - if (loggedIn != null) { - loggedIn(this, args); - } - - if (!args.Cancel) { - if (this.UsePersistentCookie == LogOnPersistence.SessionAndPersistentIdentifier) { - Page.Response.SetCookie(CreateIdentifierPersistingCookie(response)); - } - - switch (this.LogOnMode) { - case LogOnSiteNotification.FormsAuthentication: - FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, this.UsePersistentCookie == LogOnPersistence.PersistentAuthentication); - break; - case LogOnSiteNotification.None: - default: - break; - } - } - } - - /// <summary> - /// Fires the <see cref="LoggingIn"/> event. - /// </summary> - /// <param name="request">The request.</param> - /// <returns> - /// Returns whether the login should proceed. False if some event handler canceled the request. - /// </returns> - protected virtual bool OnLoggingIn(IAuthenticationRequest request) { - Contract.Requires<ArgumentNullException>(request != null); - - EventHandler<OpenIdEventArgs> loggingIn = this.LoggingIn; - - OpenIdEventArgs args = new OpenIdEventArgs(request); - if (loggingIn != null) { - loggingIn(this, args); - } - - return !args.Cancel; - } - - /// <summary> - /// Fires the <see cref="Canceled"/> event. - /// </summary> - /// <param name="response">The response.</param> - protected virtual void OnCanceled(IAuthenticationResponse response) { - Contract.Requires<ArgumentNullException>(response != null); - Contract.Requires<ArgumentException>(response.Status == AuthenticationStatus.Canceled); - - var canceled = this.Canceled; - if (canceled != null) { - canceled(this, new OpenIdEventArgs(response)); - } - } - - /// <summary> - /// Fires the <see cref="Failed"/> event. - /// </summary> - /// <param name="response">The response.</param> - protected virtual void OnFailed(IAuthenticationResponse response) { - Contract.Requires<ArgumentNullException>(response != null); - Contract.Requires<ArgumentException>(response.Status == AuthenticationStatus.Failed); - - var failed = this.Failed; - if (failed != null) { - failed(this, new OpenIdEventArgs(response)); - } - } - - /// <summary> - /// Creates the relying party instance used to generate authentication requests. - /// </summary> - /// <returns>The instantiated relying party.</returns> - protected OpenIdRelyingParty CreateRelyingParty() { - IOpenIdApplicationStore store = this.Stateless ? null : OpenIdElement.Configuration.RelyingParty.ApplicationStore.CreateInstance(OpenIdRelyingParty.HttpApplicationStore); - return this.CreateRelyingParty(store); - } - - /// <summary> - /// Creates the relying party instance used to generate authentication requests. - /// </summary> - /// <param name="store">The store to pass to the relying party constructor.</param> - /// <returns>The instantiated relying party.</returns> - protected virtual OpenIdRelyingParty CreateRelyingParty(IOpenIdApplicationStore store) { - return new OpenIdRelyingParty(store); - } - - /// <summary> - /// Configures the relying party. - /// </summary> - /// <param name="relyingParty">The relying party.</param> - [SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "relyingParty", Justification = "This makes it possible for overrides to see the value before it is set on a field.")] - protected virtual void ConfigureRelyingParty(OpenIdRelyingParty relyingParty) { - Contract.Requires<ArgumentNullException>(relyingParty != null); - - // Only set RequireSsl to true, as we don't want to override - // a .config setting of true with false. - if (this.RequireSsl) { - relyingParty.SecuritySettings.RequireSsl = true; - } - } - - /// <summary> - /// Detects whether a popup window should be used to show the Provider's UI. - /// </summary> - /// <param name="request">The request.</param> - /// <returns> - /// <c>true</c> if a popup should be used; <c>false</c> otherwise. - /// </returns> - protected virtual bool IsPopupAppropriate(IAuthenticationRequest request) { - Contract.Requires<ArgumentNullException>(request != null); - - switch (this.Popup) { - case PopupBehavior.Never: - return false; - case PopupBehavior.Always: - return true; - case PopupBehavior.IfProviderSupported: - return request.DiscoveryResult.IsExtensionSupported<UIRequest>(); - default: - throw ErrorUtilities.ThrowInternal("Unexpected value for Popup property."); - } - } - - /// <summary> - /// Adds attributes to an HTML <A> tag that will be written by the caller using - /// <see cref="HtmlTextWriter.RenderBeginTag(HtmlTextWriterTag)"/> after this method. - /// </summary> - /// <param name="writer">The HTML writer.</param> - /// <param name="request">The outgoing authentication request.</param> - /// <param name="windowStatus">The text to try to display in the status bar on mouse hover.</param> - protected void RenderOpenIdMessageTransmissionAsAnchorAttributes(HtmlTextWriter writer, IAuthenticationRequest request, string windowStatus) { - Contract.Requires<ArgumentNullException>(writer != null); - Contract.Requires<ArgumentNullException>(request != null); - - // We render a standard HREF attribute for non-javascript browsers. - writer.AddAttribute(HtmlTextWriterAttribute.Href, request.RedirectingResponse.GetDirectUriRequest(this.RelyingParty.Channel).AbsoluteUri); - - // And for the Javascript ones we do the extra work to use form POST where necessary. - writer.AddAttribute(HtmlTextWriterAttribute.Onclick, this.CreateGetOrPostAHrefValue(request) + " return false;"); - - writer.AddStyleAttribute(HtmlTextWriterStyle.Cursor, "pointer"); - if (!string.IsNullOrEmpty(windowStatus)) { - writer.AddAttribute("onMouseOver", "window.status = " + MessagingUtilities.GetSafeJavascriptValue(windowStatus)); - writer.AddAttribute("onMouseOut", "window.status = null"); - } - } - - /// <summary> - /// Creates the identifier-persisting cookie, either for saving or deleting. - /// </summary> - /// <param name="response">The positive authentication response; or <c>null</c> to clear the cookie.</param> - /// <returns>An persistent cookie.</returns> - private static HttpCookie CreateIdentifierPersistingCookie(IAuthenticationResponse response) { - HttpCookie cookie = new HttpCookie(PersistentIdentifierCookieName); - bool clearingCookie = false; - - // We'll try to store whatever it was the user originally typed in, but fallback - // to the final claimed_id. - if (response != null && response.Status == AuthenticationStatus.Authenticated) { - var positiveResponse = (PositiveAuthenticationResponse)response; - - // We must escape the value because XRIs start with =, and any leading '=' gets dropped (by ASP.NET?) - cookie.Value = Uri.EscapeDataString(positiveResponse.Endpoint.UserSuppliedIdentifier ?? response.ClaimedIdentifier); - } else { - clearingCookie = true; - cookie.Value = string.Empty; - if (HttpContext.Current.Request.Browser["supportsEmptyStringInCookieValue"] == "false") { - cookie.Value = "NoCookie"; - } - } - - if (clearingCookie) { - // mark the cookie has having already expired to cause the user agent to delete - // the old persisted cookie. - cookie.Expires = DateTime.Now.Subtract(TimeSpan.FromDays(1)); - } else { - // Make the cookie persistent by setting an expiration date - cookie.Expires = DateTime.Now + PersistentIdentifierTimeToLiveDefault; - } - - return cookie; - } - - /// <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; - if (this.ReturnToUrl != null) { - string returnToResolvedPath = this.ResolveUrl(this.ReturnToUrl); - returnToApproximation = new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, returnToResolvedPath); - } else { - returnToApproximation = 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.DiscoveryResult.IsExtensionSupported<UIRequest>()) { - // Inform the OP that we'll be using a popup window consistent with the UI extension. - // But beware that the extension MAY have already been added if we're using - // the OpenIdAjaxRelyingParty class. - if (!((AuthenticationRequest)req).Extensions.OfType<UIRequest>().Any()) { - 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, but at this point - // only save those properties that are not expected to be changed by a - // LoggingIn event handler. - req.SetUntrustedCallbackArgument(ReturnToReceivingControlId, this.ClientID); - - // Apply the control's association preference to this auth request, but only if - // it is less demanding (greater ordinal value) than the existing one. - // That way, we protect against retrying an association that was already attempted. - var authReq = ((AuthenticationRequest)req); - if (authReq.AssociationPreference < this.AssociationPreference) { - authReq.AssociationPreference = this.AssociationPreference; - } - - if (this.OnLoggingIn(req)) { - // We save this property after firing OnLoggingIn so that the host page can - // change its value and have that value saved. - req.SetUntrustedCallbackArgument(UsePersistentCookieCallbackKey, this.UsePersistentCookie.ToString()); - - 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> - /// <returns>The javascript that should execute.</returns> - private string CreateGetOrPostAHrefValue(IAuthenticationRequest request) { - Contract.Requires<ArgumentNullException>(request != null); - - Uri directUri = request.RedirectingResponse.GetDirectUriRequest(this.RelyingParty.Channel); - return "window.dnoa_internal.GetOrPost(" + MessagingUtilities.GetSafeJavascriptValue(directUri.AbsoluteUri) + ");"; - } - - /// <summary> - /// Wires the return page to immediately display a popup window with the Provider in it. - /// </summary> - /// <param name="request">The request.</param> - private void ScriptPopupWindow(IAuthenticationRequest request) { - Contract.Requires<ArgumentNullException>(request != null); - Contract.Requires<InvalidOperationException>(this.RelyingParty != null); - - StringBuilder startupScript = new StringBuilder(); - - // Add a callback function that the popup window can call on this, the - // parent window, to pass back the authentication result. - startupScript.AppendLine("window.dnoa_internal = {};"); - startupScript.AppendLine("window.dnoa_internal.processAuthorizationResult = function(uri) { window.location = uri; };"); - startupScript.AppendLine("window.dnoa_internal.popupWindow = function() {"); - startupScript.AppendFormat( - @"\tvar openidPopup = {0}", - UIUtilities.GetWindowPopupScript(this.RelyingParty, request, "openidPopup")); - startupScript.AppendLine("};"); - - this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "loginPopup", startupScript.ToString(), true); - } - - /// <summary> - /// Tries to preset the <see cref="Identifier"/> property based on a persistent - /// cookie on the browser. - /// </summary> - /// <returns> - /// A value indicating whether the <see cref="Identifier"/> property was - /// successfully preset to some non-empty value. - /// </returns> - private bool TryPresetIdentifierWithCookie() { - HttpCookie cookie = this.Page.Request.Cookies[PersistentIdentifierCookieName]; - if (cookie != null) { - this.Identifier = Uri.UnescapeDataString(cookie.Value); - return true; - } - - return false; - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.js b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.js deleted file mode 100644 index 58b283d..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.js +++ /dev/null @@ -1,172 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdRelyingPartyControlBase.js" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// This file may be used and redistributed under the terms of the -// Microsoft Public License (Ms-PL) http://opensource.org/licenses/ms-pl.html -// </copyright> -//----------------------------------------------------------------------- - -// Options that can be set on the host page: -//window.openid_visible_iframe = true; // causes the hidden iframe to show up -//window.openid_trace = true; // causes lots of messages - -trace = function(msg, color) { - if (window.openid_trace) { - if (!window.openid_tracediv) { - window.openid_tracediv = document.createElement("ol"); - document.body.appendChild(window.openid_tracediv); - } - var el = document.createElement("li"); - if (color) { el.style.color = color; } - el.appendChild(document.createTextNode(msg)); - window.openid_tracediv.appendChild(el); - //alert(msg); - } -}; - -if (window.dnoa_internal === undefined) { - window.dnoa_internal = {}; -} - -/// <summary>Instantiates an object that provides string manipulation services for URIs.</summary> -window.dnoa_internal.Uri = function(url) { - this.originalUri = url.toString(); - - this.toString = function() { - return this.originalUri; - }; - - this.getAuthority = function() { - var authority = this.getScheme() + "://" + this.getHost(); - return authority; - }; - - this.getHost = function() { - var hostStartIdx = this.originalUri.indexOf("://") + 3; - var hostEndIndex = this.originalUri.indexOf("/", hostStartIdx); - if (hostEndIndex < 0) { hostEndIndex = this.originalUri.length; } - var host = this.originalUri.substr(hostStartIdx, hostEndIndex - hostStartIdx); - return host; - }; - - this.getScheme = function() { - var schemeStartIdx = this.indexOf("://"); - return this.originalUri.substr(this.originalUri, schemeStartIdx); - }; - - this.trimFragment = function() { - var hashmark = this.originalUri.indexOf('#'); - if (hashmark >= 0) { - return new window.dnoa_internal.Uri(this.originalUri.substr(0, hashmark)); - } - return this; - }; - - this.appendQueryVariable = function(name, value) { - var pair = encodeURI(name) + "=" + encodeURI(value); - if (this.originalUri.indexOf('?') >= 0) { - this.originalUri = this.originalUri + "&" + pair; - } else { - this.originalUri = this.originalUri + "?" + pair; - } - }; - - function KeyValuePair(key, value) { - this.key = key; - this.value = value; - } - - this.pairs = []; - - var queryBeginsAt = this.originalUri.indexOf('?'); - if (queryBeginsAt >= 0) { - this.queryString = this.originalUri.substr(queryBeginsAt + 1); - var queryStringPairs = this.queryString.split('&'); - - for (var i = 0; i < queryStringPairs.length; i++) { - var equalsAt = queryStringPairs[i].indexOf('='); - left = (equalsAt >= 0) ? queryStringPairs[i].substring(0, equalsAt) : null; - right = (equalsAt >= 0) ? queryStringPairs[i].substring(equalsAt + 1) : queryStringPairs[i]; - this.pairs.push(new KeyValuePair(unescape(left), unescape(right))); - } - } - - this.getQueryArgValue = function(key) { - for (var i = 0; i < this.pairs.length; i++) { - if (this.pairs[i].key == key) { - return this.pairs[i].value; - } - } - }; - - this.getPairs = function() { - return this.pairs; - }; - - this.containsQueryArg = function(key) { - return this.getQueryArgValue(key); - }; - - this.getUriWithoutQueryOrFragement = function() { - var queryBeginsAt = this.originalUri.indexOf('?'); - if (queryBeginsAt >= 0) { - return this.originalUri.substring(0, queryBeginsAt); - } else { - var fragmentBeginsAt = this.originalUri.indexOf('#'); - if (fragmentBeginsAt >= 0) { - return this.originalUri.substring(0, fragmentBeginsAt); - } else { - return this.originalUri; - } - } - }; - - this.indexOf = function(args) { - return this.originalUri.indexOf(args); - }; - - return this; -}; - -/// <summary>Creates a hidden iframe.</summary> -window.dnoa_internal.createHiddenIFrame = function() { - var iframe = document.createElement("iframe"); - if (!window.openid_visible_iframe) { - iframe.setAttribute("width", 0); - iframe.setAttribute("height", 0); - iframe.setAttribute("style", "display: none"); - iframe.setAttribute("border", 0); - } - - return iframe; -}; - -/// <summary>Redirects the current window/frame to the given URI, -/// either using a GET or a POST as required by the length of the URL.</summary> -window.dnoa_internal.GetOrPost = function(uri) { - var maxGetLength = 2 * 1024; // keep in sync with DotNetOpenAuth.Messaging.Channel.IndirectMessageGetToPostThreshold - uri = new window.dnoa_internal.Uri(uri); - - if (uri.toString().length <= maxGetLength) { - window.location = uri.toString(); - } else { - trace("Preparing to POST: " + uri.toString()); - var iframe = window.dnoa_internal.createHiddenIFrame(); - document.body.appendChild(iframe); - var doc = iframe.ownerDocument; - var form = doc.createElement('form'); - form.action = uri.getUriWithoutQueryOrFragement(); - form.method = "POST"; - form.target = "_top"; - for (var i = 0; i < uri.getPairs().length; i++) { - var input = doc.createElement('input'); - input.type = 'hidden'; - input.name = uri.getPairs()[i].key; - input.value = uri.getPairs()[i].value; - trace(input.name + " = " + input.value); - form.appendChild(input); - } - doc.body.appendChild(form); - form.submit(); - } -}; diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdSelector.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdSelector.cs deleted file mode 100644 index ae1037b..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdSelector.cs +++ /dev/null @@ -1,455 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdSelector.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -[assembly: System.Web.UI.WebResource(DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector.EmbeddedScriptResourceName, "text/javascript")] -[assembly: System.Web.UI.WebResource(DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector.EmbeddedStylesheetResourceName, "text/css")] - -namespace DotNetOpenAuth.OpenId.RelyingParty { - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.ComponentModel; - using System.Diagnostics.Contracts; - using System.Globalization; - using System.IdentityModel.Claims; - using System.Linq; - using System.Text; - using System.Web; - using System.Web.UI; - using System.Web.UI.HtmlControls; - using System.Web.UI.WebControls; - using DotNetOpenAuth.ComponentModel; - ////using DotNetOpenAuth.InfoCard; - using DotNetOpenAuth.Messaging; - - /// <summary> - /// An ASP.NET control that provides a user-friendly way of logging into a web site using OpenID. - /// </summary> - [ToolboxData("<{0}:OpenIdSelector runat=\"server\"></{0}:OpenIdSelector>")] - public class OpenIdSelector : OpenIdRelyingPartyAjaxControlBase { - /// <summary> - /// The name of the manifest stream containing the OpenIdButtonPanel.js file. - /// </summary> - internal const string EmbeddedScriptResourceName = Util.DefaultNamespace + ".OpenId.RelyingParty.OpenIdSelector.js"; - - /// <summary> - /// The name of the manifest stream containing the OpenIdButtonPanel.css file. - /// </summary> - internal const string EmbeddedStylesheetResourceName = Util.DefaultNamespace + ".OpenId.RelyingParty.OpenIdSelector.css"; - - /// <summary> - /// The substring to append to the end of the id or name of this control to form the - /// unique name of the hidden field that will carry the positive assertion on postback. - /// </summary> - private const string AuthDataFormKeySuffix = "_openidAuthData"; - - #region ViewState keys - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="Buttons"/> property. - /// </summary> - private const string ButtonsViewStateKey = "Buttons"; - - /// <summary> - /// The viewstate key to use for storing the value of the <see cref="AuthenticatedAsToolTip"/> property. - /// </summary> - private const string AuthenticatedAsToolTipViewStateKey = "AuthenticatedAsToolTip"; - - #endregion - - #region Property defaults - - /// <summary> - /// The default value for the <see cref="AuthenticatedAsToolTip"/> property. - /// </summary> - private const string AuthenticatedAsToolTipDefault = "We recognize you!"; - - #endregion - - /// <summary> - /// The OpenIdAjaxTextBox that remains hidden until the user clicks the OpenID button. - /// </summary> - private OpenIdAjaxTextBox textBox; - - /// <summary> - /// The hidden field that will transmit the positive assertion to the RP. - /// </summary> - private HiddenField positiveAssertionField; - - /// <summary> - /// Initializes a new instance of the <see cref="OpenIdSelector"/> class. - /// </summary> - public OpenIdSelector() { - } - - /////// <summary> - /////// Occurs when an InfoCard has been submitted and decoded. - /////// </summary> - ////public event EventHandler<ReceivedTokenEventArgs> ReceivedToken; - - /////// <summary> - /////// Occurs when [token processing error]. - /////// </summary> - ////public event EventHandler<TokenProcessingErrorEventArgs> TokenProcessingError; - - /// <summary> - /// Gets the text box where applicable. - /// </summary> - public OpenIdAjaxTextBox TextBox { - get { - this.EnsureChildControlsAreCreatedSafe(); - return this.textBox; - } - } - - /// <summary> - /// Gets or sets the maximum number of OpenID Providers to simultaneously try to authenticate with. - /// </summary> - [Browsable(true), DefaultValue(OpenIdAjaxTextBox.ThrottleDefault), Category(BehaviorCategory)] - [Description("The maximum number of OpenID Providers to simultaneously try to authenticate with.")] - public int Throttle { - get { - this.EnsureChildControlsAreCreatedSafe(); - return this.textBox.Throttle; - } - - set { - this.EnsureChildControlsAreCreatedSafe(); - this.textBox.Throttle = value; - } - } - - /// <summary> - /// Gets or sets the time duration for the AJAX control to wait for an OP to respond before reporting failure to the user. - /// </summary> - [Browsable(true), DefaultValue(typeof(TimeSpan), "00:00:08"), Category(BehaviorCategory)] - [Description("The time duration for the AJAX control to wait for an OP to respond before reporting failure to the user.")] - public TimeSpan Timeout { - get { - this.EnsureChildControlsAreCreatedSafe(); - return this.textBox.Timeout; - } - - set { - this.EnsureChildControlsAreCreatedSafe(); - this.textBox.Timeout = value; - } - } - - /// <summary> - /// Gets or sets the tool tip text that appears on the green checkmark when authentication succeeds. - /// </summary> - [Bindable(true), DefaultValue(AuthenticatedAsToolTipDefault), Localizable(true), Category(AppearanceCategory)] - [Description("The tool tip text that appears on the green checkmark when authentication succeeds.")] - public string AuthenticatedAsToolTip { - get { return (string)(this.ViewState[AuthenticatedAsToolTipViewStateKey] ?? AuthenticatedAsToolTipDefault); } - set { this.ViewState[AuthenticatedAsToolTipViewStateKey] = value ?? string.Empty; } - } - - /// <summary> - /// Gets or sets a value indicating whether the Yahoo! User Interface Library (YUI) - /// will be downloaded in order to provide a login split button. - /// </summary> - /// <value> - /// <c>true</c> to use a split button; otherwise, <c>false</c> to use a standard HTML button - /// or a split button by downloading the YUI library yourself on the hosting web page. - /// </value> - /// <remarks> - /// The split button brings in about 180KB of YUI javascript dependencies. - /// </remarks> - [Bindable(true), DefaultValue(OpenIdAjaxTextBox.DownloadYahooUILibraryDefault), Category(BehaviorCategory)] - [Description("Whether a split button will be used for the \"log in\" when the user provides an identifier that delegates to more than one Provider.")] - public bool DownloadYahooUILibrary { - get { - this.EnsureChildControlsAreCreatedSafe(); - return this.textBox.DownloadYahooUILibrary; - } - - set { - this.EnsureChildControlsAreCreatedSafe(); - this.textBox.DownloadYahooUILibrary = value; - } - } - - /// <summary> - /// Gets the collection of buttons this selector should render to the browser. - /// </summary> - [PersistenceMode(PersistenceMode.InnerProperty)] - public Collection<SelectorButton> Buttons { - get { - if (this.ViewState[ButtonsViewStateKey] == null) { - var providers = new Collection<SelectorButton>(); - this.ViewState[ButtonsViewStateKey] = providers; - return providers; - } else { - return (Collection<SelectorButton>)this.ViewState[ButtonsViewStateKey]; - } - } - } - - /// <summary> - /// Gets a <see cref="T:System.Web.UI.ControlCollection"/> object that represents the child controls for a specified server control in the UI hierarchy. - /// </summary> - /// <returns> - /// The collection of child controls for the specified server control. - /// </returns> - public override ControlCollection Controls { - get { - this.EnsureChildControls(); - return base.Controls; - } - } - - /// <summary> - /// Gets the name of the open id auth data form key (for the value as stored at the user agent as a FORM field). - /// </summary> - /// <value> - /// Usually a concatenation of the control's name and <c>"_openidAuthData"</c>. - /// </value> - protected override string OpenIdAuthDataFormKey { - get { return this.UniqueID + AuthDataFormKeySuffix; } - } - - /// <summary> - /// Gets a value indicating whether some button in the selector will want - /// to display the <see cref="OpenIdAjaxTextBox"/> control. - /// </summary> - protected virtual bool OpenIdTextBoxVisible { - get { return this.Buttons.OfType<SelectorOpenIdButton>().Any(); } - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources - /// </summary> - /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected override void Dispose(bool disposing) { - if (disposing) { - foreach (var button in this.Buttons.OfType<IDisposable>()) { - button.Dispose(); - } - } - - base.Dispose(disposing); - } - - /// <summary> - /// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering. - /// </summary> - protected override void CreateChildControls() { - this.EnsureChildControlsAreCreatedSafe(); - - base.CreateChildControls(); - - // Now do the ID specific work. - this.EnsureID(); - ErrorUtilities.VerifyInternal(!string.IsNullOrEmpty(this.UniqueID), "Control.EnsureID() failed to give us a unique ID. Try setting an ID on the OpenIdSelector control. But please also file this bug with the project owners."); - - this.Controls.Add(this.textBox); - - this.positiveAssertionField.ID = this.ID + AuthDataFormKeySuffix; - this.Controls.Add(this.positiveAssertionField); - } - - /// <summary> - /// Ensures that the child controls have been built, but doesn't set control - /// properties that require executing <see cref="Control.EnsureID"/> in order to avoid - /// certain initialization order problems. - /// </summary> - /// <remarks> - /// We don't just call EnsureChildControls() and then set the property on - /// this.textBox itself because (apparently) setting this property in the ASPX - /// page and thus calling this EnsureID() via EnsureChildControls() this early - /// results in no ID. - /// </remarks> - protected virtual void EnsureChildControlsAreCreatedSafe() { - // If we've already created the child controls, this method is a no-op. - if (this.textBox != null) { - return; - } - - ////var selectorButton = this.Buttons.OfType<SelectorInfoCardButton>().FirstOrDefault(); - ////if (selectorButton != null) { - //// var selector = selectorButton.InfoCardSelector; - //// selector.ClaimsRequested.Add(new ClaimType { Name = ClaimTypes.PPID }); - //// selector.ImageSize = InfoCardImageSize.Size60x42; - //// selector.ReceivedToken += this.InfoCardSelector_ReceivedToken; - //// selector.TokenProcessingError += this.InfoCardSelector_TokenProcessingError; - //// this.Controls.Add(selector); - ////} - - this.textBox = new OpenIdAjaxTextBox(); - this.textBox.ID = "openid_identifier"; - this.textBox.HookFormSubmit = false; - this.textBox.ShowLogOnPostBackButton = true; - - this.positiveAssertionField = new HiddenField(); - } - - /// <summary> - /// Raises the <see cref="E:System.Web.UI.Control.Init"/> event. - /// </summary> - /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param> - protected override void OnInit(EventArgs e) { - base.OnInit(e); - - // We force child control creation here so that they can get postback events. - EnsureChildControls(); - } - - /// <summary> - /// Raises the <see cref="E:System.Web.UI.Control.PreRender"/> event. - /// </summary> - /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param> - protected override void OnPreRender(EventArgs e) { - base.OnPreRender(e); - - this.EnsureValidButtons(); - - var css = new HtmlLink(); - try { - css.Href = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), EmbeddedStylesheetResourceName); - css.Attributes["rel"] = "stylesheet"; - css.Attributes["type"] = "text/css"; - ErrorUtilities.VerifyHost(this.Page.Header != null, OpenIdStrings.HeadTagMustIncludeRunatServer); - this.Page.Header.Controls.AddAt(0, css); // insert at top so host page can override - } catch { - css.Dispose(); - throw; - } - - // Import the .js file where most of the code is. - this.Page.ClientScript.RegisterClientScriptResource(typeof(OpenIdSelector), EmbeddedScriptResourceName); - - // Provide javascript with a way to post the login assertion. - const string PostLoginAssertionMethodName = "postLoginAssertion"; - const string PositiveAssertionParameterName = "positiveAssertion"; - const string ScriptFormat = @"window.{2} = function({0}) {{ - $('#{3}')[0].setAttribute('value', {0}); - {1}; -}};"; - string script = string.Format( - CultureInfo.InvariantCulture, - ScriptFormat, - PositiveAssertionParameterName, - this.Page.ClientScript.GetPostBackEventReference(this, null, false), - PostLoginAssertionMethodName, - this.positiveAssertionField.ClientID); - this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "Postback", script, true); - - this.PreloadDiscovery(this.Buttons.OfType<SelectorProviderButton>().Select(op => op.OPIdentifier).Where(id => id != null)); - this.textBox.Visible = this.OpenIdTextBoxVisible; - } - - /// <summary> - /// Sends server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object, which writes the content to be rendered on the client. - /// </summary> - /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param> - protected override void Render(HtmlTextWriter writer) { - Contract.Assume(writer != null, "Missing contract"); - writer.AddAttribute(HtmlTextWriterAttribute.Class, "OpenIdProviders"); - writer.RenderBeginTag(HtmlTextWriterTag.Ul); - - foreach (var button in this.Buttons) { - button.RenderLeadingAttributes(writer); - - writer.RenderBeginTag(HtmlTextWriterTag.Li); - - writer.AddAttribute(HtmlTextWriterAttribute.Href, "#"); - writer.RenderBeginTag(HtmlTextWriterTag.A); - - writer.RenderBeginTag(HtmlTextWriterTag.Div); - writer.RenderBeginTag(HtmlTextWriterTag.Div); - - button.RenderButtonContent(writer, this); - - writer.RenderEndTag(); // </div> - - writer.AddAttribute(HtmlTextWriterAttribute.Class, "ui-widget-overlay"); - writer.RenderBeginTag(HtmlTextWriterTag.Div); - writer.RenderEndTag(); - - writer.RenderEndTag(); // </div> - writer.RenderEndTag(); // </a> - writer.RenderEndTag(); // </li> - } - - writer.RenderEndTag(); // </ul> - - if (this.textBox.Visible) { - writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none"); - writer.AddAttribute(HtmlTextWriterAttribute.Id, "OpenIDForm"); - writer.RenderBeginTag(HtmlTextWriterTag.Div); - - this.textBox.RenderControl(writer); - - writer.RenderEndTag(); // </div> - } - - this.positiveAssertionField.RenderControl(writer); - } - - /////// <summary> - /////// Fires the <see cref="ReceivedToken"/> event. - /////// </summary> - /////// <param name="e">The token, if it was decrypted.</param> - ////protected virtual void OnReceivedToken(ReceivedTokenEventArgs e) { - //// Contract.Requires(e != null); - //// ErrorUtilities.VerifyArgumentNotNull(e, "e"); - - //// var receivedInfoCard = this.ReceivedToken; - //// if (receivedInfoCard != null) { - //// receivedInfoCard(this, e); - //// } - ////} - - /////// <summary> - /////// Raises the <see cref="E:TokenProcessingError"/> event. - /////// </summary> - /////// <param name="e">The <see cref="DotNetOpenAuth.InfoCard.TokenProcessingErrorEventArgs"/> instance containing the event data.</param> - ////protected virtual void OnTokenProcessingError(TokenProcessingErrorEventArgs e) { - //// Contract.Requires(e != null); - //// ErrorUtilities.VerifyArgumentNotNull(e, "e"); - - //// var tokenProcessingError = this.TokenProcessingError; - //// if (tokenProcessingError != null) { - //// tokenProcessingError(this, e); - //// } - ////} - - /////// <summary> - /////// Handles the ReceivedToken event of the infoCardSelector control. - /////// </summary> - /////// <param name="sender">The source of the event.</param> - /////// <param name="e">The <see cref="DotNetOpenAuth.InfoCard.ReceivedTokenEventArgs"/> instance containing the event data.</param> - ////private void InfoCardSelector_ReceivedToken(object sender, ReceivedTokenEventArgs e) { - //// this.Page.Response.SetCookie(new HttpCookie("openid_identifier", "infocard") { - //// Path = this.Page.Request.ApplicationPath, - //// }); - //// this.OnReceivedToken(e); - ////} - - /////// <summary> - /////// Handles the TokenProcessingError event of the infoCardSelector control. - /////// </summary> - /////// <param name="sender">The source of the event.</param> - /////// <param name="e">The <see cref="DotNetOpenAuth.InfoCard.TokenProcessingErrorEventArgs"/> instance containing the event data.</param> - ////private void InfoCardSelector_TokenProcessingError(object sender, TokenProcessingErrorEventArgs e) { - //// this.OnTokenProcessingError(e); - ////} - - /// <summary> - /// Ensures the <see cref="Buttons"/> collection has a valid set of buttons. - /// </summary> - private void EnsureValidButtons() { - foreach (var button in this.Buttons) { - button.EnsureValid(); - } - - // Also make sure that there are appropriate numbers of each type of button. - // TODO: code here - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdSelector.css b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdSelector.css deleted file mode 100644 index e7eafc7..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdSelector.css +++ /dev/null @@ -1,109 +0,0 @@ -ul.OpenIdProviders -{ - padding: 0; - margin: 0px 0px 0px 0px; - list-style-type: none; - text-align: center; -} - -ul.OpenIdProviders li -{ - background-color: White; - display: inline-block; - border: 1px solid #DDD; - margin: 0px 2px 4px 2px; - height: 50px; - width: 100px; - text-align: center; - vertical-align: middle; -} - -ul.OpenIdProviders li div -{ - margin: 0; - padding: 0; - height: 50px; - width: 100px; - text-align: center; - display: table; - position: relative; - overflow: hidden; -} - -ul.OpenIdProviders li div div -{ - margin: 0; - padding: 0; - top: 50%; - display: table-cell; - vertical-align: middle; - position: static; -} - -ul.OpenIdProviders li img -{ -} - -ul.OpenIdProviders li a img -{ - border-width: 0; -} - -ul.OpenIdProviders li img.loginSuccess -{ - position: absolute; - right: 0; - bottom: 0; - display: none; -} - -ul.OpenIdProviders li.loginSuccess img.loginSuccess -{ - display: inline; -} - -ul.OpenIdProviders li a -{ - display: block; /* Chrome needs this for proper position of grayed out overlay */ - position: relative; -} - -ul.OpenIdProviders li div.ui-widget-overlay -{ - display: none; - position: absolute; - top: 0; - bottom: 0; - left: 0; - bottom: 0; -} - -ul.OpenIdProviders li.grayedOut div.ui-widget-overlay -{ - display: block; -} - -ul.OpenIdProviders li.focused -{ - border: solid 2px yellow; -} - -ul.OpenIdProviders li.infocard -{ - display: none; /* default to hiding InfoCard until the user agent determines it's supported */ - cursor: pointer; -} - -#openid_identifier -{ - width: 298px; -} - -#OpenIDForm -{ - text-align: center; -} - -#openid_login_button -{ -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdSelector.js b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdSelector.js deleted file mode 100644 index 297ea23..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdSelector.js +++ /dev/null @@ -1,196 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdSelector.js" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// This file may be used and redistributed under the terms of the -// Microsoft Public License (Ms-PL) http://opensource.org/licenses/ms-pl.html -// </copyright> -//----------------------------------------------------------------------- - -$(function() { - var hint = $.cookie('openid_identifier') || ''; - - var ajaxbox = document.getElementsByName('openid_identifier')[0]; - if (ajaxbox && hint != 'infocard') { - ajaxbox.setValue(hint); - } - - if (document.infoCard && document.infoCard.isSupported()) { - $('ul.OpenIdProviders li.infocard')[0].style.display = 'inline-block'; - } - - if (hint.length > 0) { - var ops = $('ul.OpenIdProviders li'); - ops.addClass('grayedOut'); - var matchFound = false; - ops.each(function(i, li) { - if (li.id == hint || (hint == 'infocard' && $(li).hasClass('infocard'))) { - $(li) - .removeClass('grayedOut') - .addClass('focused'); - matchFound = true; - } - }); - if (!matchFound) { - if (ajaxbox) { - $('#OpenIDButton') - .removeClass('grayedOut') - .addClass('focused'); - $('#OpenIDForm').show('slow', function() { - ajaxbox.focus(); - }); - } else { - // No OP button matched the last identifier, and there is no text box, - // so just un-gray all buttons. - ops.removeClass('grayedOut'); - } - } - } - - function showLoginSuccess(userSuppliedIdentifier, success) { - var li = document.getElementById(userSuppliedIdentifier); - if (li) { - if (success) { - $(li).addClass('loginSuccess'); - } else { - $(li).removeClass('loginSuccess'); - } - } - } - - window.dnoa_internal.addAuthSuccess(function(discoveryResult, serviceEndpoint, extensionResponses, state) { - showLoginSuccess(discoveryResult.userSuppliedIdentifier, true); - }); - - window.dnoa_internal.addAuthCleared(function(discoveryResult, serviceEndpoint) { - showLoginSuccess(discoveryResult.userSuppliedIdentifier, false); - - // If this is an OP button, renew the positive assertion. - var li = document.getElementById(discoveryResult.userSuppliedIdentifier); - if (li) { - li.loginBackground(); - } - }); - - if (ajaxbox) { - ajaxbox.onStateChanged = function(state) { - if (state == "authenticated") { - showLoginSuccess('OpenIDButton', true); - } else { - showLoginSuccess('OpenIDButton', false); // hide checkmark - } - }; - } - - function checkidSetup(identifier, timerBased) { - var openid = new window.OpenIdIdentifier(identifier); - if (!openid) { throw 'checkidSetup called without an identifier.'; } - openid.login(function(discoveryResult, respondingEndpoint, extensionResponses) { - doLogin(discoveryResult, respondingEndpoint); - }); - } - - // Sends the positive assertion we've collected to the server and actually logs the user into the RP. - function doLogin(discoveryResult, respondingEndpoint) { - var retain = true; //!$('#NotMyComputer')[0].selected; - $.cookie('openid_identifier', retain ? discoveryResult.userSuppliedIdentifier : null, { path: window.aspnetapppath }); - window.postLoginAssertion(respondingEndpoint.response.toString(), window.parent.location.href); - } - - if (ajaxbox) { - // take over how the text box does postbacks. - ajaxbox.dnoi_internal.postback = doLogin; - } - - // This FrameManager will be used for background logins for the OP buttons - // and the last used identifier. It is NOT the frame manager used by the - // OpenIdAjaxTextBox, as it has its own. - var backgroundTimeout = 3000; - - $(document).ready(function() { - var ops = $('ul.OpenIdProviders li'); - ops.each(function(i, li) { - if ($(li).hasClass('OPButton')) { - li.authenticationIFrames = new window.dnoa_internal.FrameManager(1/*throttle*/); - var openid = new window.OpenIdIdentifier(li.id); - var authFrames = li.authenticationIFrames; - if ($(li).hasClass('NoAsyncAuth')) { - li.loginBackground = function() { }; - } else { - li.loginBackground = function() { - openid.loginBackground(authFrames, null, null, backgroundTimeout); - }; - } - li.loginBackground(); - } - }); - }); - - $('ul.OpenIdProviders li').click(function() { - var lastFocus = $('.focused')[0]; - if (lastFocus != $(this)[0]) { - $('ul.OpenIdProviders li').removeClass('focused'); - $(this).addClass('focused'); - } - - // Make sure we're not graying out any OPs if the user clicked on a gray button. - var wasGrayedOut = false; - if ($(this).hasClass('grayedOut')) { - wasGrayedOut = true; - $('ul.OpenIdProviders li').removeClass('grayedOut'); - } - - // Be sure to hide the openid_identifier text box unless the OpenID button is selected. - if ($(this)[0] != $('#OpenIDButton')[0] && $('#OpenIDForm').is(':visible')) { - $('#OpenIDForm').hide('slow'); - } - - var relevantUserSuppliedIdentifier = null; - // Don't immediately login if the user clicked OpenID and he can't see the identifier box. - if ($(this)[0].id != 'OpenIDButton') { - relevantUserSuppliedIdentifier = $(this)[0].id; - } else if (ajaxbox && $('#OpenIDForm').is(':visible')) { - relevantUserSuppliedIdentifier = ajaxbox.value; - } - - var discoveryResult = window.dnoa_internal.discoveryResults[relevantUserSuppliedIdentifier]; - var respondingEndpoint = discoveryResult ? discoveryResult.findSuccessfulRequest() : null; - - // If the user clicked on a button that has the "we're ready to log you in immediately", - // then log them in! - if (respondingEndpoint) { - doLogin(discoveryResult, respondingEndpoint); - } else if ($(this).hasClass('OPButton')) { - checkidSetup($(this)[0].id); - } else if ($(this).hasClass('infocard') && wasGrayedOut) { - // we need to forward the click onto the InfoCard image so it is handled, since our - // gray overlaying div captured the click event. - $('img', this)[0].click(); - } - }); - if (ajaxbox) { - $('#OpenIDButton').click(function() { - // Be careful to only try to select the text box once it is available. - if ($('#OpenIDForm').is(':hidden')) { - $('#OpenIDForm').show('slow', function() { - ajaxbox.focus(); - }); - } else { - ajaxbox.focus(); - } - }); - - $(ajaxbox.form).keydown(function(e) { - if (e.keyCode == $.ui.keyCode.ENTER) { - // we do NOT want to submit the form on ENTER. - e.preventDefault(); - } - }); - } - - // Make popup window close on escape (the dialog style is already taken care of) - $(document).keydown(function(e) { - if (e.keyCode == $.ui.keyCode.ESCAPE) { - window.close(); - } - }); -});
\ No newline at end of file diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdTextBox.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdTextBox.cs deleted file mode 100644 index 335b435..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdTextBox.cs +++ /dev/null @@ -1,708 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="OpenIdTextBox.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -[assembly: System.Web.UI.WebResource(DotNetOpenAuth.OpenId.RelyingParty.OpenIdTextBox.EmbeddedLogoResourceName, "image/png")] - -#pragma warning disable 0809 // marking inherited, unsupported properties as obsolete to discourage their use - -namespace DotNetOpenAuth.OpenId.RelyingParty { - using System; - using System.Collections.Generic; - using System.Collections.Specialized; - 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; - using System.Web.UI; - using System.Web.UI.WebControls; - 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. - /// </summary> - /// <remarks> - /// This control offers greater UI flexibility than the <see cref="OpenIdLogin"/> - /// control, but requires more work to be done by the hosting web site to - /// assemble a complete login experience. - /// </remarks> - [DefaultProperty("Text"), ValidationProperty("Text")] - [ToolboxData("<{0}:OpenIdTextBox runat=\"server\" />")] - public class OpenIdTextBox : OpenIdRelyingPartyControlBase, IEditableTextControl, ITextControl, IPostBackDataHandler { - /// <summary> - /// The name of the manifest stream containing the - /// OpenID logo that is placed inside the text box. - /// </summary> - internal const string EmbeddedLogoResourceName = Util.DefaultNamespace + ".OpenId.RelyingParty.openid_login.png"; - - /// <summary> - /// Default value for <see cref="TabIndex"/> property. - /// </summary> - protected const short TabIndexDefault = 0; - - #region Property category constants - - /// <summary> - /// The "Simple Registration" category for properties. - /// </summary> - private const string ProfileCategory = "Simple Registration"; - - #endregion - - #region Property viewstate keys - - /// <summary> - /// The viewstate key to use for the <see cref="RequestEmail"/> property. - /// </summary> - private const string RequestEmailViewStateKey = "RequestEmail"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestNickname"/> property. - /// </summary> - private const string RequestNicknameViewStateKey = "RequestNickname"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestPostalCode"/> property. - /// </summary> - private const string RequestPostalCodeViewStateKey = "RequestPostalCode"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestCountry"/> property. - /// </summary> - private const string RequestCountryViewStateKey = "RequestCountry"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestLanguage"/> property. - /// </summary> - private const string RequestLanguageViewStateKey = "RequestLanguage"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestTimeZone"/> property. - /// </summary> - private const string RequestTimeZoneViewStateKey = "RequestTimeZone"; - - /// <summary> - /// The viewstate key to use for the <see cref="EnableRequestProfile"/> property. - /// </summary> - private const string EnableRequestProfileViewStateKey = "EnableRequestProfile"; - - /// <summary> - /// The viewstate key to use for the <see cref="PolicyUrl"/> property. - /// </summary> - private const string PolicyUrlViewStateKey = "PolicyUrl"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestFullName"/> property. - /// </summary> - private const string RequestFullNameViewStateKey = "RequestFullName"; - - /// <summary> - /// The viewstate key to use for the <see cref="PresetBorder"/> property. - /// </summary> - private const string PresetBorderViewStateKey = "PresetBorder"; - - /// <summary> - /// The viewstate key to use for the <see cref="ShowLogo"/> property. - /// </summary> - private const string ShowLogoViewStateKey = "ShowLogo"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestGender"/> property. - /// </summary> - private const string RequestGenderViewStateKey = "RequestGender"; - - /// <summary> - /// The viewstate key to use for the <see cref="RequestBirthDate"/> property. - /// </summary> - private const string RequestBirthDateViewStateKey = "RequestBirthDate"; - - /// <summary> - /// The viewstate key to use for the <see cref="CssClass"/> property. - /// </summary> - private const string CssClassViewStateKey = "CssClass"; - - /// <summary> - /// The viewstate key to use for the <see cref="MaxLength"/> property. - /// </summary> - private const string MaxLengthViewStateKey = "MaxLength"; - - /// <summary> - /// The viewstate key to use for the <see cref="Columns"/> property. - /// </summary> - private const string ColumnsViewStateKey = "Columns"; - - /// <summary> - /// The viewstate key to use for the <see cref="TabIndex"/> property. - /// </summary> - private const string TabIndexViewStateKey = "TabIndex"; - - /// <summary> - /// The viewstate key to use for the <see cref="Enabled"/> property. - /// </summary> - private const string EnabledViewStateKey = "Enabled"; - - /// <summary> - /// The viewstate key to use for the <see cref="Name"/> property. - /// </summary> - private const string NameViewStateKey = "Name"; - - /// <summary> - /// The viewstate key to use for the <see cref="Text"/> property. - /// </summary> - private const string TextViewStateKey = "Text"; - - #endregion - - #region Property defaults - - /// <summary> - /// The default value for the <see cref="Columns"/> property. - /// </summary> - private const int ColumnsDefault = 40; - - /// <summary> - /// The default value for the <see cref="MaxLength"/> property. - /// </summary> - private const int MaxLengthDefault = 40; - - /// <summary> - /// The default value for the <see cref="Name"/> property. - /// </summary> - private const string NameDefault = "openid_identifier"; - - /// <summary> - /// The default value for the <see cref="EnableRequestProfile"/> property. - /// </summary> - private const bool EnableRequestProfileDefault = true; - - /// <summary> - /// The default value for the <see cref="ShowLogo"/> property. - /// </summary> - private const bool ShowLogoDefault = true; - - /// <summary> - /// The default value for the <see cref="PresetBorder"/> property. - /// </summary> - private const bool PresetBorderDefault = true; - - /// <summary> - /// The default value for the <see cref="PolicyUrl"/> property. - /// </summary> - private const string PolicyUrlDefault = ""; - - /// <summary> - /// The default value for the <see cref="CssClass"/> property. - /// </summary> - private const string CssClassDefault = "openid"; - - /// <summary> - /// The default value for the <see cref="Text"/> property. - /// </summary> - private const string TextDefault = ""; - - /// <summary> - /// The default value for the <see cref="RequestEmail"/> property. - /// </summary> - private const DemandLevel RequestEmailDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestPostalCode"/> property. - /// </summary> - private const DemandLevel RequestPostalCodeDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestCountry"/> property. - /// </summary> - private const DemandLevel RequestCountryDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestLanguage"/> property. - /// </summary> - private const DemandLevel RequestLanguageDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestTimeZone"/> property. - /// </summary> - private const DemandLevel RequestTimeZoneDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestNickname"/> property. - /// </summary> - private const DemandLevel RequestNicknameDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestFullName"/> property. - /// </summary> - private const DemandLevel RequestFullNameDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestBirthDate"/> property. - /// </summary> - private const DemandLevel RequestBirthDateDefault = DemandLevel.NoRequest; - - /// <summary> - /// The default value for the <see cref="RequestGender"/> property. - /// </summary> - private const DemandLevel RequestGenderDefault = DemandLevel.NoRequest; - - #endregion - - /// <summary> - /// An empty sreg request, used to compare with others to see if they too are empty. - /// </summary> - private static readonly ClaimsRequest EmptyClaimsRequest = new ClaimsRequest(); - - /// <summary> - /// Initializes a new instance of the <see cref="OpenIdTextBox"/> class. - /// </summary> - public OpenIdTextBox() { - } - - #region IEditableTextControl Members - - /// <summary> - /// Occurs when the content of the text changes between posts to the server. - /// </summary> - public event EventHandler TextChanged; - - #endregion - - #region Properties - - /// <summary> - /// Gets or sets the content of the text box. - /// </summary> - [Bindable(true), DefaultValue(""), Category(AppearanceCategory)] - [Description("The content of the text box.")] - public string Text { - get { - return this.Identifier != null ? this.Identifier.OriginalString : (this.ViewState[TextViewStateKey] as string ?? string.Empty); - } - - set { - // Try to store it as a validated identifier, - // but failing that at least store the text. - Identifier id; - if (Identifier.TryParse(value, out id)) { - this.Identifier = id; - } else { - // Be sure to set the viewstate AFTER setting the Identifier, - // since setting the Identifier clears the viewstate in OnIdentifierChanged. - this.Identifier = null; - this.ViewState[TextViewStateKey] = value; - } - } - } - - /// <summary> - /// Gets or sets the form name to use for this input field. - /// </summary> - [Bindable(true), DefaultValue(NameDefault), Category(BehaviorCategory)] - [Description("The form name of this input field.")] - public string Name { - get { return (string)(this.ViewState[NameViewStateKey] ?? NameDefault); } - set { this.ViewState[NameViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the CSS class assigned to the text box. - /// </summary> - [Bindable(true), DefaultValue(CssClassDefault), Category(AppearanceCategory)] - [Description("The CSS class assigned to the text box.")] - public string CssClass { - get { return (string)this.ViewState[CssClassViewStateKey]; } - set { this.ViewState[CssClassViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets a value indicating whether to show the OpenID logo in the text box. - /// </summary> - [Bindable(true), DefaultValue(ShowLogoDefault), Category(AppearanceCategory)] - [Description("The visibility of the OpenID logo in the text box.")] - public bool ShowLogo { - get { return (bool)(this.ViewState[ShowLogoViewStateKey] ?? ShowLogoDefault); } - set { this.ViewState[ShowLogoViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets a value indicating whether to use inline styling to force a solid gray border. - /// </summary> - [Bindable(true), DefaultValue(PresetBorderDefault), Category(AppearanceCategory)] - [Description("Whether to use inline styling to force a solid gray border.")] - public bool PresetBorder { - get { return (bool)(this.ViewState[PresetBorderViewStateKey] ?? PresetBorderDefault); } - set { this.ViewState[PresetBorderViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the width of the text box in characters. - /// </summary> - [Bindable(true), DefaultValue(ColumnsDefault), Category(AppearanceCategory)] - [Description("The width of the text box in characters.")] - public int Columns { - get { return (int)(this.ViewState[ColumnsViewStateKey] ?? ColumnsDefault); } - set { this.ViewState[ColumnsViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the maximum number of characters the browser should allow - /// </summary> - [Bindable(true), DefaultValue(MaxLengthDefault), Category(AppearanceCategory)] - [Description("The maximum number of characters the browser should allow.")] - public int MaxLength { - get { return (int)(this.ViewState[MaxLengthViewStateKey] ?? MaxLengthDefault); } - set { this.ViewState[MaxLengthViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the tab index of the Web server control. - /// </summary> - /// <value></value> - /// <returns> - /// The tab index of the Web server control. The default is 0, which indicates that this property is not set. - /// </returns> - /// <exception cref="T:System.ArgumentOutOfRangeException"> - /// The specified tab index is not between -32768 and 32767. - /// </exception> - [Bindable(true), DefaultValue(TabIndexDefault), Category(BehaviorCategory)] - [Description("The tab index of the text box control.")] - public virtual short TabIndex { - get { return (short)(this.ViewState[TabIndexViewStateKey] ?? TabIndexDefault); } - set { this.ViewState[TabIndexViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets a value indicating whether this <see cref="OpenIdTextBox"/> is enabled - /// in the browser for editing and will respond to incoming OpenID messages. - /// </summary> - /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value> - [Bindable(true), DefaultValue(true), Category(BehaviorCategory)] - [Description("Whether the control is editable in the browser and will respond to OpenID messages.")] - public bool Enabled { - get { return (bool)(this.ViewState[EnabledViewStateKey] ?? true); } - set { this.ViewState[EnabledViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's nickname from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestNicknameDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's nickname from the Provider.")] - public DemandLevel RequestNickname { - get { return (DemandLevel)(ViewState[RequestNicknameViewStateKey] ?? RequestNicknameDefault); } - set { ViewState[RequestNicknameViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's email address from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestEmailDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's email address from the Provider.")] - public DemandLevel RequestEmail { - get { return (DemandLevel)(ViewState[RequestEmailViewStateKey] ?? RequestEmailDefault); } - set { ViewState[RequestEmailViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's full name from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestFullNameDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's full name from the Provider")] - public DemandLevel RequestFullName { - get { return (DemandLevel)(ViewState[RequestFullNameViewStateKey] ?? RequestFullNameDefault); } - set { ViewState[RequestFullNameViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's birthdate from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestBirthDateDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's birthdate from the Provider.")] - public DemandLevel RequestBirthDate { - get { return (DemandLevel)(ViewState[RequestBirthDateViewStateKey] ?? RequestBirthDateDefault); } - set { ViewState[RequestBirthDateViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's gender from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestGenderDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's gender from the Provider.")] - public DemandLevel RequestGender { - get { return (DemandLevel)(ViewState[RequestGenderViewStateKey] ?? RequestGenderDefault); } - set { ViewState[RequestGenderViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's postal code from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestPostalCodeDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's postal code from the Provider.")] - public DemandLevel RequestPostalCode { - get { return (DemandLevel)(ViewState[RequestPostalCodeViewStateKey] ?? RequestPostalCodeDefault); } - set { ViewState[RequestPostalCodeViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's country from the Provider. - /// </summary> - [Bindable(true)] - [Category(ProfileCategory)] - [DefaultValue(RequestCountryDefault)] - [Description("Your level of interest in receiving the user's country from the Provider.")] - public DemandLevel RequestCountry { - get { return (DemandLevel)(ViewState[RequestCountryViewStateKey] ?? RequestCountryDefault); } - set { ViewState[RequestCountryViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's preferred language from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestLanguageDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's preferred language from the Provider.")] - public DemandLevel RequestLanguage { - get { return (DemandLevel)(ViewState[RequestLanguageViewStateKey] ?? RequestLanguageDefault); } - set { ViewState[RequestLanguageViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets your level of interest in receiving the user's time zone from the Provider. - /// </summary> - [Bindable(true), DefaultValue(RequestTimeZoneDefault), Category(ProfileCategory)] - [Description("Your level of interest in receiving the user's time zone from the Provider.")] - public DemandLevel RequestTimeZone { - get { return (DemandLevel)(ViewState[RequestTimeZoneViewStateKey] ?? RequestTimeZoneDefault); } - set { ViewState[RequestTimeZoneViewStateKey] = value; } - } - - /// <summary> - /// Gets or sets the URL to your privacy policy page that describes how - /// claims will be used and/or shared. - /// </summary> - [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Bindable property must be simple type")] - [Bindable(true), DefaultValue(PolicyUrlDefault), Category(ProfileCategory)] - [Description("The URL to your privacy policy page that describes how claims will be used and/or shared.")] - [UrlProperty, Editor("System.Web.UI.Design.UrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))] - public string PolicyUrl { - get { - return (string)ViewState[PolicyUrlViewStateKey] ?? PolicyUrlDefault; - } - - set { - UriUtil.ValidateResolvableUrl(Page, DesignMode, value); - ViewState[PolicyUrlViewStateKey] = value; - } - } - - /// <summary> - /// Gets or sets a value indicating whether to use OpenID extensions - /// to retrieve profile data of the authenticating user. - /// </summary> - [Bindable(true), DefaultValue(EnableRequestProfileDefault), Category(ProfileCategory)] - [Description("Turns the entire Simple Registration extension on or off.")] - public bool EnableRequestProfile { - get { return (bool)(ViewState[EnableRequestProfileViewStateKey] ?? EnableRequestProfileDefault); } - set { ViewState[EnableRequestProfileViewStateKey] = value; } - } - - #endregion - - #region IPostBackDataHandler Members - - /// <summary> - /// When implemented by a class, processes postback data for an ASP.NET server control. - /// </summary> - /// <param name="postDataKey">The key identifier for the control.</param> - /// <param name="postCollection">The collection of all incoming name values.</param> - /// <returns> - /// true if the server control's state changes as a result of the postback; otherwise, false. - /// </returns> - bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection) { - return this.LoadPostData(postDataKey, postCollection); - } - - /// <summary> - /// When implemented by a class, signals the server control to notify the ASP.NET application that the state of the control has changed. - /// </summary> - void IPostBackDataHandler.RaisePostDataChangedEvent() { - this.RaisePostDataChangedEvent(); - } - - #endregion - - /// <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> - protected internal override IEnumerable<IAuthenticationRequest> CreateRequests(Identifier identifier) { - ErrorUtilities.VerifyArgumentNotNull(identifier, "identifier"); - - // We delegate all our logic to another method, since invoking base. methods - // within an iterator method results in unverifiable code. - return this.CreateRequestsCore(base.CreateRequests(identifier)); - } - - /// <summary> - /// Checks for incoming OpenID authentication responses and fires appropriate events. - /// </summary> - /// <param name="e">The <see cref="T:System.EventArgs"/> object that contains the event data.</param> - protected override void OnLoad(EventArgs e) { - if (!this.Enabled) { - return; - } - - this.Page.RegisterRequiresPostBack(this); - base.OnLoad(e); - } - - /// <summary> - /// Called when the <see cref="Identifier"/> property is changed. - /// </summary> - protected override void OnIdentifierChanged() { - this.ViewState.Remove(TextViewStateKey); - base.OnIdentifierChanged(); - } - - /// <summary> - /// Sends server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object, which writes the content to be rendered on the client. - /// </summary> - /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param> - protected override void Render(HtmlTextWriter writer) { - Contract.Assume(writer != null, "Missing contract."); - - if (this.ShowLogo) { - string logoUrl = Page.ClientScript.GetWebResourceUrl( - typeof(OpenIdTextBox), EmbeddedLogoResourceName); - writer.AddStyleAttribute( - HtmlTextWriterStyle.BackgroundImage, - string.Format(CultureInfo.InvariantCulture, "url({0})", HttpUtility.HtmlEncode(logoUrl))); - writer.AddStyleAttribute("background-repeat", "no-repeat"); - writer.AddStyleAttribute("background-position", "0 50%"); - writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingLeft, "18px"); - } - - if (this.PresetBorder) { - writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "solid"); - writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "1px"); - writer.AddStyleAttribute(HtmlTextWriterStyle.BorderColor, "lightgray"); - } - - if (!string.IsNullOrEmpty(this.CssClass)) { - writer.AddAttribute(HtmlTextWriterAttribute.Class, this.CssClass); - } - - writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID); - writer.AddAttribute(HtmlTextWriterAttribute.Name, HttpUtility.HtmlEncode(this.Name)); - writer.AddAttribute(HtmlTextWriterAttribute.Type, "text"); - writer.AddAttribute(HtmlTextWriterAttribute.Size, this.Columns.ToString(CultureInfo.InvariantCulture)); - writer.AddAttribute(HtmlTextWriterAttribute.Value, HttpUtility.HtmlEncode(this.Text)); - writer.AddAttribute(HtmlTextWriterAttribute.Tabindex, this.TabIndex.ToString(CultureInfo.CurrentCulture)); - - writer.RenderBeginTag(HtmlTextWriterTag.Input); - writer.RenderEndTag(); - } - - /// <summary> - /// When implemented by a class, processes postback data for an ASP.NET server control. - /// </summary> - /// <param name="postDataKey">The key identifier for the control.</param> - /// <param name="postCollection">The collection of all incoming name values.</param> - /// <returns> - /// true if the server control's state changes as a result of the postback; otherwise, false. - /// </returns> - protected virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection) { - Contract.Assume(postCollection != null, "Missing contract"); - - // If the control was temporarily hidden, it won't be in the Form data, - // and we'll just implicitly keep the last Text setting. - if (postCollection[this.Name] != null) { - this.Text = postCollection[this.Name]; - return true; - } - - return false; - } - - /// <summary> - /// When implemented by a class, signals the server control to notify the ASP.NET application that the state of the control has changed. - /// </summary> - [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "Preserve signature of interface we're implementing.")] - protected virtual void RaisePostDataChangedEvent() { - this.OnTextChanged(); - } - - /// <summary> - /// Called on a postback when the Text property has changed. - /// </summary> - protected virtual void OnTextChanged() { - EventHandler textChanged = this.TextChanged; - if (textChanged != null) { - textChanged(this, EventArgs.Empty); - } - } - - /// <summary> - /// Creates the authentication requests for a given user-supplied Identifier. - /// </summary> - /// <param name="requests">The authentication requests to prepare.</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(IEnumerable<IAuthenticationRequest> requests) { - Contract.Requires(requests != null); - - foreach (var request in requests) { - if (this.EnableRequestProfile) { - this.AddProfileArgs(request); - } - - yield return request; - } - } - - /// <summary> - /// Adds extensions to a given authentication request to ask the Provider - /// for user profile data. - /// </summary> - /// <param name="request">The authentication request to add the extensions to.</param> - private void AddProfileArgs(IAuthenticationRequest request) { - Contract.Requires<ArgumentNullException>(request != null); - - var sreg = new ClaimsRequest() { - Nickname = this.RequestNickname, - Email = this.RequestEmail, - FullName = this.RequestFullName, - BirthDate = this.RequestBirthDate, - Gender = this.RequestGender, - PostalCode = this.RequestPostalCode, - Country = this.RequestCountry, - Language = this.RequestLanguage, - TimeZone = this.RequestTimeZone, - PolicyUrl = string.IsNullOrEmpty(this.PolicyUrl) ? - null : new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.Page.ResolveUrl(this.PolicyUrl)), - }; - - // Only actually add the extension request if fields are actually being requested. - if (!sreg.Equals(EmptyClaimsRequest)) { - request.AddExtension(sreg); - } - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/PopupBehavior.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/PopupBehavior.cs deleted file mode 100644 index e84f4f5..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/PopupBehavior.cs +++ /dev/null @@ -1,31 +0,0 @@ -//----------------------------------------------------------------------- -// <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, - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/SelectorButton.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/SelectorButton.cs deleted file mode 100644 index 0be3a5f..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/SelectorButton.cs +++ /dev/null @@ -1,46 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="SelectorButton.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OpenId.RelyingParty { - using System; - using System.Diagnostics.Contracts; - using System.Web.UI; - - /// <summary> - /// A button that would appear in the <see cref="OpenIdSelector"/> control via its <see cref="OpenIdSelector.Buttons"/> collection. - /// </summary> - [ContractClass(typeof(SelectorButtonContract))] - public abstract class SelectorButton { - /// <summary> - /// Initializes a new instance of the <see cref="SelectorButton"/> class. - /// </summary> - protected SelectorButton() { - } - - /// <summary> - /// Ensures that this button has been initialized to a valid state. - /// </summary> - /// <remarks> - /// This is "internal" -- NOT "protected internal" deliberately. It makes it impossible - /// to derive from this class outside the assembly, which suits our purposes since the - /// <see cref="OpenIdSelector"/> control is not designed for an extensible set of button types. - /// </remarks> - internal abstract void EnsureValid(); - - /// <summary> - /// Renders the leading attributes for the LI tag. - /// </summary> - /// <param name="writer">The writer.</param> - protected internal abstract void RenderLeadingAttributes(HtmlTextWriter writer); - - /// <summary> - /// Renders the content of the button. - /// </summary> - /// <param name="writer">The writer.</param> - /// <param name="selector">The containing selector control.</param> - protected internal abstract void RenderButtonContent(HtmlTextWriter writer, OpenIdSelector selector); - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/SelectorButtonContract.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/SelectorButtonContract.cs deleted file mode 100644 index c70218a..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/SelectorButtonContract.cs +++ /dev/null @@ -1,46 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="SelectorButtonContract.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OpenId.RelyingParty { - using System; - using System.Diagnostics.Contracts; - using System.Web.UI; - - /// <summary> - /// The contract class for the <see cref="SelectorButton"/> class. - /// </summary> - [ContractClassFor(typeof(SelectorButton))] - internal abstract class SelectorButtonContract : SelectorButton { - /// <summary> - /// Ensures that this button has been initialized to a valid state. - /// </summary> - /// <remarks> - /// This is "internal" -- NOT "protected internal" deliberately. It makes it impossible - /// to derive from this class outside the assembly, which suits our purposes since the - /// <see cref="OpenIdSelector"/> control is not designed for an extensible set of button types. - /// </remarks> - internal override void EnsureValid() { - } - - /// <summary> - /// Renders the leading attributes for the LI tag. - /// </summary> - /// <param name="writer">The writer.</param> - protected internal override void RenderLeadingAttributes(HtmlTextWriter writer) { - Contract.Requires<ArgumentNullException>(writer != null); - } - - /// <summary> - /// Renders the content of the button. - /// </summary> - /// <param name="writer">The writer.</param> - /// <param name="selector">The containing selector control.</param> - protected internal override void RenderButtonContent(HtmlTextWriter writer, OpenIdSelector selector) { - Contract.Requires<ArgumentNullException>(writer != null); - Contract.Requires<ArgumentNullException>(selector != null); - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/SelectorOpenIdButton.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/SelectorOpenIdButton.cs deleted file mode 100644 index ac4dcbf..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/SelectorOpenIdButton.cs +++ /dev/null @@ -1,82 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="SelectorOpenIdButton.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OpenId.RelyingParty { - using System; - using System.ComponentModel; - using System.Diagnostics.Contracts; - using System.Drawing.Design; - using System.Web.UI; - using DotNetOpenAuth.Messaging; - - /// <summary> - /// A button that appears in the <see cref="OpenIdSelector"/> control that - /// allows the user to type in a user-supplied identifier. - /// </summary> - public class SelectorOpenIdButton : SelectorButton { - /// <summary> - /// Initializes a new instance of the <see cref="SelectorOpenIdButton"/> class. - /// </summary> - public SelectorOpenIdButton() { - Reporting.RecordFeatureUse(this); - } - - /// <summary> - /// Initializes a new instance of the <see cref="SelectorOpenIdButton"/> class. - /// </summary> - /// <param name="imageUrl">The image to display on the button.</param> - public SelectorOpenIdButton(string imageUrl) - : this() { - Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(imageUrl)); - - this.Image = imageUrl; - } - - /// <summary> - /// Gets or sets the path to the image to display on the button's surface. - /// </summary> - /// <value>The virtual path to the image.</value> - [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))] - [UrlProperty] - public string Image { get; set; } - - /// <summary> - /// Ensures that this button has been initialized to a valid state. - /// </summary> - internal override void EnsureValid() { - Contract.Ensures(!string.IsNullOrEmpty(this.Image)); - - // Every button must have an image. - ErrorUtilities.VerifyOperation(!string.IsNullOrEmpty(this.Image), OpenIdStrings.PropertyNotSet, "SelectorButton.Image"); - } - - /// <summary> - /// Renders the leading attributes for the LI tag. - /// </summary> - /// <param name="writer">The writer.</param> - protected internal override void RenderLeadingAttributes(HtmlTextWriter writer) { - writer.AddAttribute(HtmlTextWriterAttribute.Id, "OpenIDButton"); - writer.AddAttribute(HtmlTextWriterAttribute.Class, "OpenIDButton"); - } - - /// <summary> - /// Renders the content of the button. - /// </summary> - /// <param name="writer">The writer.</param> - /// <param name="selector">The containing selector control.</param> - protected internal override void RenderButtonContent(HtmlTextWriter writer, OpenIdSelector selector) { - writer.AddAttribute(HtmlTextWriterAttribute.Src, selector.Page.ResolveUrl(this.Image)); - writer.RenderBeginTag(HtmlTextWriterTag.Img); - writer.RenderEndTag(); - - writer.AddAttribute(HtmlTextWriterAttribute.Src, selector.Page.ClientScript.GetWebResourceUrl(typeof(OpenIdAjaxTextBox), OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName)); - writer.AddAttribute(HtmlTextWriterAttribute.Class, "loginSuccess"); - writer.AddAttribute(HtmlTextWriterAttribute.Title, selector.AuthenticatedAsToolTip); - writer.RenderBeginTag(HtmlTextWriterTag.Img); - writer.RenderEndTag(); - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/SelectorProviderButton.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/SelectorProviderButton.cs deleted file mode 100644 index 2195e73..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/SelectorProviderButton.cs +++ /dev/null @@ -1,113 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="SelectorProviderButton.cs" company="Andrew Arnott"> -// Copyright (c) Andrew Arnott. All rights reserved. -// </copyright> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.OpenId.RelyingParty { - using System; - using System.ComponentModel; - using System.Diagnostics.Contracts; - using System.Drawing.Design; - using System.Web.UI; - using DotNetOpenAuth.ComponentModel; - using DotNetOpenAuth.Messaging; - - /// <summary> - /// A button that appears in the <see cref="OpenIdSelector"/> control that - /// provides one-click access to a popular OpenID Provider. - /// </summary> - public class SelectorProviderButton : SelectorButton { - /// <summary> - /// Initializes a new instance of the <see cref="SelectorProviderButton"/> class. - /// </summary> - public SelectorProviderButton() { - Reporting.RecordFeatureUse(this); - } - - /// <summary> - /// Initializes a new instance of the <see cref="SelectorProviderButton"/> class. - /// </summary> - /// <param name="providerIdentifier">The OP Identifier.</param> - /// <param name="imageUrl">The image to display on the button.</param> - public SelectorProviderButton(Identifier providerIdentifier, string imageUrl) - : this() { - Contract.Requires<ArgumentNullException>(providerIdentifier != null); - Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(imageUrl)); - - this.OPIdentifier = providerIdentifier; - this.Image = imageUrl; - } - - /// <summary> - /// Gets or sets the path to the image to display on the button's surface. - /// </summary> - /// <value>The virtual path to the image.</value> - [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))] - [UrlProperty] - public string Image { get; set; } - - /// <summary> - /// Gets or sets the OP Identifier represented by the button. - /// </summary> - /// <value> - /// The OP identifier, which may be provided in the easiest "user-supplied identifier" form, - /// but for security should be provided with a leading https:// if possible. - /// For example: "yahoo.com" or "https://me.yahoo.com/". - /// </value> - [TypeConverter(typeof(IdentifierConverter))] - public Identifier OPIdentifier { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this Provider doesn't handle - /// checkid_immediate messages correctly and background authentication - /// should not be attempted. - /// </summary> - public bool SkipBackgroundAuthentication { get; set; } - - /// <summary> - /// Ensures that this button has been initialized to a valid state. - /// </summary> - internal override void EnsureValid() { - Contract.Ensures(!string.IsNullOrEmpty(this.Image)); - Contract.Ensures(this.OPIdentifier != null); - - // Every button must have an image. - ErrorUtilities.VerifyOperation(!string.IsNullOrEmpty(this.Image), OpenIdStrings.PropertyNotSet, "SelectorButton.Image"); - - // Every button must have exactly one purpose. - ErrorUtilities.VerifyOperation(this.OPIdentifier != null, OpenIdStrings.PropertyNotSet, "SelectorButton.OPIdentifier"); - } - - /// <summary> - /// Renders the leading attributes for the LI tag. - /// </summary> - /// <param name="writer">The writer.</param> - protected internal override void RenderLeadingAttributes(HtmlTextWriter writer) { - writer.AddAttribute(HtmlTextWriterAttribute.Id, this.OPIdentifier); - - string style = "OPButton"; - if (this.SkipBackgroundAuthentication) { - style += " NoAsyncAuth"; - } - writer.AddAttribute(HtmlTextWriterAttribute.Class, style); - } - - /// <summary> - /// Renders the content of the button. - /// </summary> - /// <param name="writer">The writer.</param> - /// <param name="selector">The containing selector control.</param> - protected internal override void RenderButtonContent(HtmlTextWriter writer, OpenIdSelector selector) { - writer.AddAttribute(HtmlTextWriterAttribute.Src, selector.Page.ResolveUrl(this.Image)); - writer.RenderBeginTag(HtmlTextWriterTag.Img); - writer.RenderEndTag(); - - writer.AddAttribute(HtmlTextWriterAttribute.Src, selector.Page.ClientScript.GetWebResourceUrl(typeof(OpenIdAjaxTextBox), OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName)); - writer.AddAttribute(HtmlTextWriterAttribute.Class, "loginSuccess"); - writer.AddAttribute(HtmlTextWriterAttribute.Title, selector.AuthenticatedAsToolTip); - writer.RenderBeginTag(HtmlTextWriterTag.Img); - writer.RenderEndTag(); - } - } -} diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/login_failure.png b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/login_failure.png Binary files differdeleted file mode 100644 index 8003700..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/login_failure.png +++ /dev/null diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/login_success (lock).png b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/login_success (lock).png Binary files differdeleted file mode 100644 index bc0c0c8..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/login_success (lock).png +++ /dev/null diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/login_success.png b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/login_success.png Binary files differdeleted file mode 100644 index 0ae1365..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/login_success.png +++ /dev/null diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/openid_login.png b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/openid_login.png Binary files differdeleted file mode 100644 index caebd58..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/openid_login.png +++ /dev/null diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/spinner.gif b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/spinner.gif Binary files differdeleted file mode 100644 index 9cb298e..0000000 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/spinner.gif +++ /dev/null diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/Properties/AssemblyInfo.cs index 2961dc2..e2dd3d0 100644 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/Properties/AssemblyInfo.cs +++ b/src/DotNetOpenAuth.OpenId.RelyingParty/Properties/AssemblyInfo.cs @@ -50,7 +50,9 @@ using System.Web.UI; [assembly: InternalsVisibleTo("DotNetOpenAuth.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OpenId.Provider, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.OpenId.RelyingParty.UI, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] #else [assembly: InternalsVisibleTo("DotNetOpenAuth.Test")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OpenId.Provider")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.OpenId.RelyingParty.UI")] #endif |