diff options
6 files changed, 197 insertions, 70 deletions
diff --git a/projecttemplates/MvcRelyingParty/Global.asax.cs b/projecttemplates/MvcRelyingParty/Global.asax.cs index 14772ae..34f7a81 100644 --- a/projecttemplates/MvcRelyingParty/Global.asax.cs +++ b/projecttemplates/MvcRelyingParty/Global.asax.cs @@ -26,6 +26,9 @@ "Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = string.Empty }); + routes.MapRoute( + "OpenIdDiscover", + "Account/Discover"); } protected void Application_Start() { diff --git a/projecttemplates/MvcRelyingParty/Views/Account/LogOnScripts.ascx b/projecttemplates/MvcRelyingParty/Views/Account/LogOnScripts.ascx index 1f0e752..e983872 100644 --- a/projecttemplates/MvcRelyingParty/Views/Account/LogOnScripts.ascx +++ b/projecttemplates/MvcRelyingParty/Views/Account/LogOnScripts.ascx @@ -1,72 +1,6 @@ <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> -<script type="text/javascript" language="javascript"><!-- - //<![CDATA[ - //window.openid_visible_iframe = true; // causes the hidden iframe to show up - //window.openid_trace = true; // causes lots of messages -//]]>--></script> +<%@ Import Namespace="DotNetOpenAuth.Mvc" %> <script type="text/javascript" src='<%= Url.Content("~/Scripts/MicrosoftAjax.js") %>'></script> <script type="text/javascript" src='<%= Url.Content("~/Scripts/MicrosoftMvcAjax.js") %>'></script> <script type="text/javascript" src='<%= Url.Content("~/Scripts/jquery.cookie.js") %>'></script> -<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/yuiloader/yuiloader-min.js"></script> -<script type="text/javascript" src="<%=Page.ClientScript.GetWebResourceUrl(typeof(DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector), "DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyControlBase.js")%>"></script> -<script type="text/javascript" src="<%=Page.ClientScript.GetWebResourceUrl(typeof(DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector), "DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyAjaxControlBase.js")%>"></script> -<script type="text/javascript" src="<%=Page.ClientScript.GetWebResourceUrl(typeof(DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector), "DotNetOpenAuth.OpenId.RelyingParty.OpenIdAjaxTextBox.js")%>"></script> -<script type="text/javascript" language="javascript"><!-- - //<![CDATA[ - try { - if (YAHOO) { - var loader = new YAHOO.util.YUILoader({ - require: ['button', 'menu'], - loadOptional: false, - combine: true - }); - - loader.insert(); - } - } catch (e) { } - window.aspnetapppath = '/'; - window.dnoa_internal.maxPositiveAssertionLifetime = 5 * 60 * 1000; - window.dnoa_internal.callbackAsync = 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: '<%= Url.Action("Discover") %>?identifier=' + encodeURIComponent(argument) - }); - }; - window.postLoginAssertion = function (positiveAssertion) { - $('#openid_openidAuthData')[0].setAttribute('value', positiveAssertion); - if (!$('#ReturnUrl')[0].value) { // popups have no ReturnUrl predefined, but full page LogOn does. - $('#ReturnUrl')[0].setAttribute('value', window.parent.location.href); - } - document.forms[0].submit(); - }; - $(function () { - var box = document.getElementsByName('openid_identifier')[0]; - initAjaxOpenId( - box, - '<%=Page.ClientScript.GetWebResourceUrl(typeof(DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector), "DotNetOpenAuth.OpenId.RelyingParty.openid_login.gif")%>', - '<%=Page.ClientScript.GetWebResourceUrl(typeof(DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector), "DotNetOpenAuth.OpenId.RelyingParty.spinner.gif")%>', - '<%=Page.ClientScript.GetWebResourceUrl(typeof(DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector), "DotNetOpenAuth.OpenId.RelyingParty.login_success.png")%>', - '<%=Page.ClientScript.GetWebResourceUrl(typeof(DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector), "DotNetOpenAuth.OpenId.RelyingParty.login_failure.png")%>', - 3, // throttle - 8000, // timeout - null, // js function to invoke on receiving a positive assertion - "LOG IN", - "Click here to log in using a pop-up window.", - true, // ShowLogOnPostBackButton - "Click here to log in immediately.", - "RETRY", - "Retry a failed identifier discovery.", - "Discovering/authenticating", - "Please correct errors in OpenID identifier and allow login to complete before submitting.", - "Please wait for login to complete.", - "Authenticated by {0}.", - "Authenticated as {0}.", - "Authentication failed.", - false, // auto postback - null); // PostBackEventReference (unused in MVC) - }); -//]]>--></script> -<script type="text/javascript" src="<%=Page.ClientScript.GetWebResourceUrl(typeof(DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector), "DotNetOpenAuth.OpenId.RelyingParty.OpenIdSelector.js")%>"></script> +<%= Html.OpenIdSelectorScripts(this.Page, new OpenIdSelectorOptions { })%> diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj index 4847b37..aaeb501 100644 --- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj +++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj @@ -302,6 +302,8 @@ http://opensource.org/licenses/ms-pl.html <Compile Include="Messaging\Reflection\IMessagePartEncoder.cs" /> <Compile Include="Messaging\Reflection\IMessagePartNullEncoder.cs" /> <Compile Include="Messaging\Reflection\MessageDescriptionCollection.cs" /> + <Compile Include="Mvc\OpenIdHelper.cs" /> + <Compile Include="Mvc\OpenIdSelectorOptions.cs" /> <Compile Include="OAuth\ChannelElements\ICombinedOpenIdProviderTokenManager.cs" /> <Compile Include="OAuth\ChannelElements\IConsumerDescription.cs" /> <Compile Include="OAuth\ChannelElements\IConsumerTokenManager.cs" /> diff --git a/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs b/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs new file mode 100644 index 0000000..6a6107f --- /dev/null +++ b/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs @@ -0,0 +1,161 @@ +//----------------------------------------------------------------------- +// <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.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.RelyingParty; + + public static class OpenIdHelper { + public static string OpenIdSelectorScripts(this HtmlHelper html, Page page, OpenIdSelectorOptions options) { + Contract.Requires<ArgumentNullException>(html != null); + Contract.Requires<ArgumentNullException>(page != null); + Contract.Requires<ArgumentNullException>(options != null); + + StringWriter result = new StringWriter(); + + if (options.ShowDiagnosticIFrame || options.ShowDiagnosticTrace) { + result.WriteScriptBlock(string.Format( + CultureInfo.InvariantCulture, +@"window.openid_visible_iframe = {0}; // causes the hidden iframe to show up +window.openid_trace = {1}; // causes lots of messages", + options.ShowDiagnosticIFrame ? "true" : "false", + options.ShowDiagnosticTrace ? "true" : "false")); + } + result.WriteScriptTags(page, new[] { + OpenIdRelyingPartyControlBase.EmbeddedJavascriptResource, + OpenIdRelyingPartyAjaxControlBase.EmbeddedAjaxJavascriptResource, + OpenIdAjaxTextBox.EmbeddedScriptResourceName, + }); + + if (options.DownloadYahooUILibrary) { + result.WriteScriptTags(new[] { "https://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/yuiloader/yuiloader-min.js" }); + } + + var blockBuilder = new StringWriter(); + if (options.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(DotNetOpenAuthSection.Configuration.OpenId.MaxAuthenticationTime.TotalMilliseconds, DotNetOpenAuthSection.Configuration.Messaging.MaximumMessageLifetime.TotalMilliseconds)); + blockBuilder.WriteLine( + "{0} = {1};", + OpenIdRelyingPartyAjaxControlBase.MaxPositiveAssertionLifetimeJsName, + assertionLifetimeInMilliseconds.ToString(CultureInfo.InvariantCulture)); + + string discoverUrl = VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath) + html.RouteCollection["OpenIdDiscover"].GetVirtualPath(html.ViewContext.RequestContext, new RouteValueDictionary(new { identifier = "xxx" })).VirtualPath; + blockBuilder.WriteLine(@" {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)) + }}); + }};", + OpenIdRelyingPartyAjaxControlBase.CallbackJSFunctionAsync, + discoverUrl); + + blockBuilder.WriteLine(@" window.postLoginAssertion = function (positiveAssertion) {{ + $('#{0}')[0].setAttribute('value', positiveAssertion); + if (!$('#ReturnUrl')[0].value) {{ // popups have no ReturnUrl predefined, but full page LogOn does. + $('#ReturnUrl')[0].setAttribute('value', window.parent.location.href); + }} + document.forms[0].submit(); + }};", + options.AssertionHiddenFieldId); + + blockBuilder.WriteLine(@" $(function () {{ + var box = document.getElementsByName('openid_identifier')[0]; + initAjaxOpenId( + box, + {0}, + {1}, + {2}, + {3}, + 3, // throttle + 8000, // timeout + null, // js function to invoke on receiving a positive assertion + 'LOG IN', + 'Click here to log in using a pop-up window.', + true, // ShowLogOnPostBackButton + 'Click here to log in immediately.', + 'RETRY', + 'Retry a failed identifier discovery.', + 'Discovering/authenticating', + 'Please correct errors in OpenID identifier and allow login to complete before submitting.', + 'Please wait for login to complete.', + 'Authenticated by {{0}}.', + 'Authenticated as {{0}}.', + 'Authentication failed.', + false, // auto postback + null); // PostBackEventReference (unused in MVC) + }});", + MessagingUtilities.GetSafeJavascriptValue(page.ClientScript.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenIdTextBox.EmbeddedLogoResourceName)), + MessagingUtilities.GetSafeJavascriptValue(page.ClientScript.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenIdAjaxTextBox.EmbeddedSpinnerResourceName)), + MessagingUtilities.GetSafeJavascriptValue(page.ClientScript.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName)), + MessagingUtilities.GetSafeJavascriptValue(page.ClientScript.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenIdAjaxTextBox.EmbeddedLoginFailureResourceName))); + + result.WriteScriptBlock(blockBuilder.ToString()); + result.WriteScriptTags(page, OpenIdSelector.EmbeddedScriptResourceName); + return result.ToString(); + } + + private static void WriteScriptTags(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); + } + } + + private static void WriteScriptTags(this TextWriter writer, Page page, string resourceName) { + WriteScriptTags(writer, page, new[] { resourceName }); + } + + private static void WriteScriptTags(this TextWriter writer, Page page, IEnumerable<string> resourceNames) { + Contract.Requires<ArgumentNullException>(writer != null); + Contract.Requires<ArgumentNullException>(page != null); + Contract.Requires<ArgumentNullException>(resourceNames != null); + + writer.WriteScriptTags(resourceNames.Select(r => page.ClientScript.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), r))); + } + + private static void WriteScriptBlock(this TextWriter writer, string script) { + writer.WriteLine("<script type='text/javascript' language='javascript'><!--"); + writer.WriteLine("//<![CDATA["); + writer.WriteLine(script); + writer.WriteLine("//]]>--></script>"); + } + } +} diff --git a/src/DotNetOpenAuth/Mvc/OpenIdSelectorOptions.cs b/src/DotNetOpenAuth/Mvc/OpenIdSelectorOptions.cs new file mode 100644 index 0000000..487851b --- /dev/null +++ b/src/DotNetOpenAuth/Mvc/OpenIdSelectorOptions.cs @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------- +// <copyright file="OpenIdSelectorOptions.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Mvc { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + public class OpenIdSelectorOptions { + public OpenIdSelectorOptions() { + this.DownloadYahooUILibrary = true; + this.AssertionHiddenFieldId = "openid_openidAuthData"; + } + + public bool DownloadYahooUILibrary { get; set; } + + public string AssertionHiddenFieldId { get; set; } + + public bool ShowDiagnosticTrace { get; set; } + + public bool ShowDiagnosticIFrame { get; set; } + } +} diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs index 1de2fc2..7d6a9d5 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs @@ -48,13 +48,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// <summary> /// The name of the javascript function that will initiate an asynchronous callback. /// </summary> - protected const string CallbackJSFunctionAsync = "window.dnoa_internal.callbackAsync"; + protected internal const string CallbackJSFunctionAsync = "window.dnoa_internal.callbackAsync"; /// <summary> /// The name of the javascript field that stores the maximum time a positive assertion is /// good for before it must be refreshed. /// </summary> - private const string MaxPositiveAssertionLifetimeJsName = "window.dnoa_internal.maxPositiveAssertionLifetime"; + internal const string MaxPositiveAssertionLifetimeJsName = "window.dnoa_internal.maxPositiveAssertionLifetime"; #region Property viewstate keys |