summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs')
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs468
1 files changed, 0 insertions, 468 deletions
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);
- }
- }
-}