summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-12-26 07:04:33 -0800
committerAndrew Arnott <andrewarnott@gmail.com>2009-12-26 07:04:33 -0800
commit8a677d2d2320e96e4b70e994e978804a5cc358fc (patch)
tree25353095c2f3d5bbb940d47e8f612cafcdd4aa44 /src
parentce37861c9507e338fc81314898b3a30888310b55 (diff)
parent72f5ee12a341eaca93075fb0f4705bec7cc84631 (diff)
downloadDotNetOpenAuth-8a677d2d2320e96e4b70e994e978804a5cc358fc.zip
DotNetOpenAuth-8a677d2d2320e96e4b70e994e978804a5cc358fc.tar.gz
DotNetOpenAuth-8a677d2d2320e96e4b70e994e978804a5cc358fc.tar.bz2
Merge branch 'reports' into v3.3
Conflicts: projecttemplates/WebFormsRelyingParty/Web.config src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth.BuildTasks/CompareFiles.cs27
-rw-r--r--src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs14
-rw-r--r--src/DotNetOpenAuth.sln16
-rw-r--r--src/DotNetOpenAuth/Logger.cs10
-rw-r--r--src/DotNetOpenAuth/Messaging/Bindings/StandardReplayProtectionBindingElement.cs1
-rw-r--r--src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs1
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs8
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/StandardProviderApplicationStore.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs12
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs22
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.cs42
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.js64
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs15
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs9
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/SelectorOpenIdButton.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/SelectorProviderButton.cs3
20 files changed, 206 insertions, 62 deletions
diff --git a/src/DotNetOpenAuth.BuildTasks/CompareFiles.cs b/src/DotNetOpenAuth.BuildTasks/CompareFiles.cs
index 691df20..51fcee4 100644
--- a/src/DotNetOpenAuth.BuildTasks/CompareFiles.cs
+++ b/src/DotNetOpenAuth.BuildTasks/CompareFiles.cs
@@ -81,5 +81,32 @@ namespace DotNetOpenAuth.BuildTasks {
return true;
}
+
+ /// <summary>
+ /// Tests whether a file is up to date with respect to another,
+ /// based on existence, last write time and file size.
+ /// </summary>
+ /// <param name="sourcePath">The source path.</param>
+ /// <param name="destPath">The dest path.</param>
+ /// <returns><c>true</c> if the files are the same; <c>false</c> if the files are different</returns>
+ internal static bool FastFileEqualityCheck(string sourcePath, string destPath) {
+ FileInfo sourceInfo = new FileInfo(sourcePath);
+ FileInfo destInfo = new FileInfo(destPath);
+
+ if (sourceInfo.Exists ^ destInfo.Exists) {
+ // Either the source file or the destination file is missing.
+ return false;
+ }
+
+ if (!sourceInfo.Exists) {
+ // Neither file exists.
+ return true;
+ }
+
+ // We'll say the files are the same if their modification date and length are the same.
+ return
+ sourceInfo.LastWriteTimeUtc == destInfo.LastWriteTimeUtc &&
+ sourceInfo.Length == destInfo.Length;
+ }
}
}
diff --git a/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs b/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs
index 3b81978..e17d8f2 100644
--- a/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs
+++ b/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs
@@ -18,15 +18,6 @@ namespace DotNetOpenAuth.BuildTasks {
/// </summary>
public class CopyWithTokenSubstitution : Task {
/// <summary>
- /// Gets or sets a value indicating whether the task should
- /// skip the copying of files that are unchanged between the source and destination.
- /// </summary>
- /// <value>
- /// <c>true</c> to skip copying files where the destination files are newer than the source files; otherwise, <c>false</c> to copy all files.
- /// </value>
- public bool SkipUnchangedFiles { get; set; }
-
- /// <summary>
/// Gets or sets the files to copy.
/// </summary>
/// <value>The files to copy.</value>
@@ -65,8 +56,11 @@ namespace DotNetOpenAuth.BuildTasks {
for (int i = 0; i < this.SourceFiles.Length; i++) {
string sourcePath = this.SourceFiles[i].ItemSpec;
string destPath = this.DestinationFiles[i].ItemSpec;
+ bool skipUnchangedFiles = bool.Parse(this.SourceFiles[i].GetMetadata("SkipUnchangedFiles"));
- if (this.SkipUnchangedFiles && File.GetLastWriteTimeUtc(sourcePath) < File.GetLastWriteTimeUtc(destPath)) {
+ // We deliberably consider newer destination files to be up-to-date rather than
+ // requiring equality because this task modifies the destination file while copying.
+ if (skipUnchangedFiles && File.GetLastWriteTimeUtc(sourcePath) < File.GetLastWriteTimeUtc(destPath)) {
Log.LogMessage(MessageImportance.Low, "Skipping \"{0}\" -> \"{1}\" because the destination is up to date.", sourcePath, destPath);
continue;
}
diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln
index 3233865..569a7bc 100644
--- a/src/DotNetOpenAuth.sln
+++ b/src/DotNetOpenAuth.sln
@@ -7,6 +7,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.Test", "DotN
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{20B5E173-C3C4-49F8-BD25-E69044075B4D}"
ProjectSection(SolutionItems) = preProject
+ ..\build.proj = ..\build.proj
DotNetOpenAuth.vsmdi = DotNetOpenAuth.vsmdi
..\LICENSE.txt = ..\LICENSE.txt
LocalTestRun.testrunconfig = LocalTestRun.testrunconfig
@@ -169,6 +170,11 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebFormsRelyingParty", "..\projecttemplates\WebFormsRelyingParty\WebFormsRelyingParty.csproj", "{A78F8FC6-7B03-4230-BE41-761E400D6810}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelyingPartyLogic", "..\projecttemplates\RelyingPartyLogic\RelyingPartyLogic.csproj", "{17932639-1F50-48AF-B0A5-E2BF832F82CC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {2B4261AC-25AC-4B8D-B459-1C42B6B1401D} = {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}
+ EndProjectSection
+EndProject
+Project("{C8D11400-126E-41CD-887F-60BD40844F9E}") = "RelyingPartyDatabase", "..\projecttemplates\RelyingPartyDatabase\RelyingPartyDatabase.dbproj", "{2B4261AC-25AC-4B8D-B459-1C42B6B1401D}"
EndProject
Global
GlobalSection(TestCaseManagementSettings) = postSolution
@@ -276,6 +282,15 @@ Global
{17932639-1F50-48AF-B0A5-E2BF832F82CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{17932639-1F50-48AF-B0A5-E2BF832F82CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{17932639-1F50-48AF-B0A5-E2BF832F82CC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU
+ {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU
+ {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.CodeAnalysis|Any CPU.Deploy.0 = Debug|Any CPU
+ {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -298,5 +313,6 @@ Global
{5C65603B-235F-47E6-B536-06385C60DE7F} = {E9ED920D-1F83-48C0-9A4B-09CCE505FE6D}
{A78F8FC6-7B03-4230-BE41-761E400D6810} = {B9EB8729-4B54-4453-B089-FE6761BA3057}
{17932639-1F50-48AF-B0A5-E2BF832F82CC} = {B9EB8729-4B54-4453-B089-FE6761BA3057}
+ {2B4261AC-25AC-4B8D-B459-1C42B6B1401D} = {B9EB8729-4B54-4453-B089-FE6761BA3057}
EndGlobalSection
EndGlobal
diff --git a/src/DotNetOpenAuth/Logger.cs b/src/DotNetOpenAuth/Logger.cs
index a9dbef2..48007ed 100644
--- a/src/DotNetOpenAuth/Logger.cs
+++ b/src/DotNetOpenAuth/Logger.cs
@@ -60,6 +60,11 @@ namespace DotNetOpenAuth {
private static readonly ILog http = Create("DotNetOpenAuth.Http");
/// <summary>
+ /// Backing field for the <see cref="Controls"/> property.
+ /// </summary>
+ private static readonly ILog controls = Create("DotNetOpenAuth.Controls");
+
+ /// <summary>
/// Backing field for the <see cref="OpenId"/> property.
/// </summary>
private static readonly ILog openId = Create("DotNetOpenAuth.OpenId");
@@ -110,6 +115,11 @@ namespace DotNetOpenAuth {
internal static ILog Http { get { return http; } }
/// <summary>
+ /// Gets the logger for events logged by ASP.NET controls.
+ /// </summary>
+ internal static ILog Controls { get { return controls; } }
+
+ /// <summary>
/// Gets the logger for high-level OpenID events.
/// </summary>
internal static ILog OpenId { get { return openId; } }
diff --git a/src/DotNetOpenAuth/Messaging/Bindings/StandardReplayProtectionBindingElement.cs b/src/DotNetOpenAuth/Messaging/Bindings/StandardReplayProtectionBindingElement.cs
index 0a7ddbd..bb56cfd 100644
--- a/src/DotNetOpenAuth/Messaging/Bindings/StandardReplayProtectionBindingElement.cs
+++ b/src/DotNetOpenAuth/Messaging/Bindings/StandardReplayProtectionBindingElement.cs
@@ -125,6 +125,7 @@ namespace DotNetOpenAuth.Messaging.Bindings {
ErrorUtilities.VerifyProtocol(nonceMessage.Nonce.Length > 0 || this.AllowZeroLengthNonce, MessagingStrings.InvalidNonceReceived);
if (!this.nonceStore.StoreNonce(nonceMessage.NonceContext, nonceMessage.Nonce, nonceMessage.UtcCreationDate)) {
+ Logger.OpenId.ErrorFormat("Replayed nonce detected ({0} {1}). Rejecting message.", nonceMessage.Nonce, nonceMessage.UtcCreationDate);
throw new ReplayedMessageException(message);
}
diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs
index 1c20f1d..4fa70a0 100644
--- a/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs
+++ b/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs
@@ -223,7 +223,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
yield return extension;
}
} else {
- Logger.OpenId.WarnFormat("Extension with type URI '{0}' ignored because it is not a recognized extension.", typeUri);
+ Logger.OpenId.DebugFormat("Extension with type URI '{0}' ignored because it is not a recognized extension.", typeUri);
}
}
}
diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs
index 9040404..817407c 100644
--- a/src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs
+++ b/src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs
@@ -187,6 +187,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
IReplayProtectedProtocolMessage replayResponse = response;
if (!this.nonceStore.StoreNonce(replayResponse.NonceContext, nonce.RandomPartAsString, nonce.CreationDateUtc)) {
+ Logger.OpenId.ErrorFormat("Replayed nonce detected ({0} {1}). Rejecting message.", replayResponse.Nonce, replayResponse.UtcCreationDate);
throw new ReplayedMessageException(message);
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs b/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs
index cd7575e..9d3f576 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs
@@ -47,12 +47,12 @@ namespace DotNetOpenAuth.OpenId.Extensions {
var req = (RelyingParty.AuthenticationRequest)request;
var sreg = req.AppliedExtensions.OfType<ClaimsRequest>().SingleOrDefault();
if (sreg == null) {
- Logger.OpenId.Warn("No Simple Registration (ClaimsRequest) extension present in the request to spread to AX.");
+ Logger.OpenId.Debug("No Simple Registration (ClaimsRequest) extension present in the request to spread to AX.");
return;
}
if (req.Provider.IsExtensionSupported<ClaimsRequest>()) {
- Logger.OpenId.Info("Skipping generation of AX request because the Identifier advertises the Provider supports the Sreg extension.");
+ Logger.OpenId.Debug("Skipping generation of AX request because the Identifier advertises the Provider supports the Sreg extension.");
return;
}
@@ -65,11 +65,11 @@ namespace DotNetOpenAuth.OpenId.Extensions {
// Try to use just one AX Type URI format if we can figure out which type the OP accepts.
AXAttributeFormats detectedFormat;
if (TryDetectOPAttributeFormat(request, out detectedFormat)) {
- Logger.OpenId.Info("Detected OP support for AX but not for Sreg. Removing Sreg extension request and using AX instead.");
+ Logger.OpenId.Debug("Detected OP support for AX but not for Sreg. Removing Sreg extension request and using AX instead.");
attributeFormats = detectedFormat;
req.Extensions.Remove(sreg);
} else {
- Logger.OpenId.Info("Could not determine whether OP supported Sreg or AX. Using both extensions.");
+ Logger.OpenId.Debug("Could not determine whether OP supported Sreg or AX. Using both extensions.");
}
foreach (AXAttributeFormats format in ForEachFormat(attributeFormats)) {
diff --git a/src/DotNetOpenAuth/OpenId/Provider/StandardProviderApplicationStore.cs b/src/DotNetOpenAuth/OpenId/Provider/StandardProviderApplicationStore.cs
index 7085e72..f33a655 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/StandardProviderApplicationStore.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/StandardProviderApplicationStore.cs
@@ -122,7 +122,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// </summary>
/// <param name="context">The context, or namespace, within which the <paramref name="nonce"/> must be unique.</param>
/// <param name="nonce">A series of random characters.</param>
- /// <param name="timestamp">The timestamp that together with the nonce string make it unique.
+ /// <param name="timestampUtc">The timestamp that together with the nonce string make it unique.
/// The timestamp may also be used by the data store to clear out old nonces.</param>
/// <returns>
/// True if the nonce+timestamp (combination) was not previously in the database.
@@ -135,8 +135,8 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// is retrieved or set using the
/// <see cref="StandardExpirationBindingElement.MaximumMessageAge"/> property.
/// </remarks>
- public bool StoreNonce(string context, string nonce, DateTime timestamp) {
- return this.nonceStore.StoreNonce(context, nonce, timestamp);
+ public bool StoreNonce(string context, string nonce, DateTime timestampUtc) {
+ return this.nonceStore.StoreNonce(context, nonce, timestampUtc);
}
#endregion
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
index f1851a0..a317b95 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
@@ -416,7 +416,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
var failedAssociationEndpoints = new List<ServiceEndpoint>(0);
foreach (var endpoint in endpoints) {
- Logger.OpenId.InfoFormat("Creating authentication request for user supplied Identifier: {0}", userSuppliedIdentifier);
+ Logger.OpenId.DebugFormat("Creating authentication request for user supplied Identifier: {0}", userSuppliedIdentifier);
// The strategy here is to prefer endpoints with whom we can create associations.
Association association = null;
@@ -446,10 +446,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
if (relyingParty.SecuritySettings.RequireAssociation) {
Logger.OpenId.Warn("Associations could not be formed with some Providers. Security settings require shared associations for authentication requests so these will be skipped.");
} else {
- Logger.OpenId.WarnFormat("Now generating requests for Provider endpoints that failed initial association attempts.");
+ Logger.OpenId.Debug("Now generating requests for Provider endpoints that failed initial association attempts.");
foreach (var endpoint in failedAssociationEndpoints) {
- Logger.OpenId.WarnFormat("Creating authentication request for user supplied Identifier: {0}", userSuppliedIdentifier);
+ Logger.OpenId.DebugFormat("Creating authentication request for user supplied Identifier: {0} at endpoint: {1}", userSuppliedIdentifier, endpoint.ProviderEndpoint.AbsoluteUri);
// Create the auth request, but prevent it from attempting to create an association
// because we've already tried. Let's not have it waste time trying again.
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
index 4249834..f646599 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
@@ -704,6 +704,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
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
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs
index 44a5b41..0254346 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs
@@ -174,6 +174,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
};
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
@@ -416,10 +420,14 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Notifies the user agent via an AJAX response of a completed authentication attempt.
/// </summary>
protected override void ScriptClosingPopupOrIFrame() {
- Logger.OpenId.InfoFormat("AJAX (iframe) callback from OP: {0}", this.Page.Request.Url);
+ Logger.OpenId.DebugFormat("AJAX (iframe) callback from OP: {0}", this.Page.Request.Url);
string extensionsJson = null;
var authResponse = RelyingPartyNonVerifying.GetResponse();
+ Logger.Controls.DebugFormat(
+ "The {0} control checked for an authentication response from a popup window or iframe using a non-verifying RP and found: {1}",
+ this.ID,
+ authResponse.Status);
if (authResponse.Status == AuthenticationStatus.Authenticated) {
this.OnUnconfirmedPositiveAssertion(); // event handler will fill the clientScriptExtensions collection.
var extensionsDictionary = new Dictionary<string, string>();
@@ -613,7 +621,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <param name="methodCall">The method to call on the OpenIdAjaxTextBox, including
/// parameters. (i.e. "callback('arg1', 2)"). No escaping is done by this method.</param>
private void CallbackUserAgentMethod(string methodCall) {
- Logger.OpenId.InfoFormat("Sending Javascript callback: {0}", methodCall);
+ Logger.OpenId.DebugFormat("Sending Javascript callback: {0}", methodCall);
Page.Response.Write(@"<html><body><script language='javascript'>
var inPopup = !window.frameElement;
var objSrc = inPopup ? window.opener : window.frameElement;
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
index 538e9f2..2420fd6 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
@@ -482,6 +482,16 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <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() {
@@ -608,11 +618,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
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.
+ // 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 == null || receiver == this.ClientID) {
+ 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);
}
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.cs
index ed83412..e93383d 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.cs
@@ -81,6 +81,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private HiddenField positiveAssertionField;
/// <summary>
+ /// A field to store the value to set on the <see cref="textBox"/> control after it's created.
+ /// </summary>
+ private bool downloadYuiLibrary = OpenIdAjaxTextBox.DownloadYahooUILibraryDefault;
+
+ /// <summary>
/// Initializes a new instance of the <see cref="OpenIdSelector"/> class.
/// </summary>
public OpenIdSelector() {
@@ -121,13 +126,19 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[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.EnsureChildControls();
- return this.textBox.DownloadYahooUILibrary;
+ return this.textBox != null ? this.textBox.DownloadYahooUILibrary : this.downloadYuiLibrary;
}
set {
- this.EnsureChildControls();
- this.textBox.DownloadYahooUILibrary = value;
+ // 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.
+ if (this.textBox != null) {
+ this.textBox.DownloadYahooUILibrary = value;
+ } else {
+ this.downloadYuiLibrary = value;
+ }
}
}
@@ -171,6 +182,14 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <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>
@@ -190,6 +209,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
protected override void CreateChildControls() {
base.CreateChildControls();
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.");
var selectorButton = this.Buttons.OfType<SelectorInfoCardButton>().FirstOrDefault();
if (selectorButton != null) {
@@ -205,6 +225,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.textBox.ID = "openid_identifier";
this.textBox.HookFormSubmit = false;
this.textBox.ShowLogOnPostBackButton = true;
+ this.textBox.DownloadYahooUILibrary = this.downloadYuiLibrary;
this.Controls.Add(this.textBox);
this.positiveAssertionField = new HiddenField();
@@ -259,6 +280,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
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>
@@ -295,13 +317,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
writer.RenderEndTag(); // </ul>
- writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");
- writer.AddAttribute(HtmlTextWriterAttribute.Id, "OpenIDForm");
- writer.RenderBeginTag(HtmlTextWriterTag.Div);
+ if (this.textBox.Visible) {
+ writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");
+ writer.AddAttribute(HtmlTextWriterAttribute.Id, "OpenIDForm");
+ writer.RenderBeginTag(HtmlTextWriterTag.Div);
- this.textBox.RenderControl(writer);
+ this.textBox.RenderControl(writer);
- writer.RenderEndTag(); // </div>
+ writer.RenderEndTag(); // </div>
+ }
this.positiveAssertionField.RenderControl(writer);
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.js b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.js
index 6271952..c58e06e 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.js
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.js
@@ -10,7 +10,7 @@ $(function() {
var hint = $.cookie('openid_identifier') || '';
var ajaxbox = document.getElementsByName('openid_identifier')[0];
- if (hint != 'infocard') {
+ if (ajaxbox && hint != 'infocard') {
ajaxbox.setValue(hint);
}
@@ -31,12 +31,18 @@ $(function() {
}
});
if (!matchFound) {
- $('#OpenIDButton')
- .removeClass('grayedOut')
- .addClass('focused');
- $('#OpenIDForm').show('slow', function() {
- ajaxbox.focus();
- });
+ 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');
+ }
}
}
@@ -65,13 +71,15 @@ $(function() {
}
});
- ajaxbox.onStateChanged = function(state) {
- if (state == "authenticated") {
- showLoginSuccess('OpenIDButton', true);
- } else {
- showLoginSuccess('OpenIDButton', false); // hide checkmark
- }
- };
+ 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);
@@ -88,8 +96,10 @@ $(function() {
window.postLoginAssertion(respondingEndpoint.response.toString(), window.parent.location.href);
}
- // take over how the text box does postbacks.
- ajaxbox.dnoi_internal.postback = doLogin;
+ 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
@@ -138,7 +148,7 @@ $(function() {
// 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 ($('#OpenIDForm').is(':visible')) {
+ } else if (ajaxbox && $('#OpenIDForm').is(':visible')) {
relevantUserSuppliedIdentifier = ajaxbox.value;
}
@@ -157,16 +167,18 @@ $(function() {
$('img', this)[0].click();
}
});
- $('#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() {
+ 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();
- });
- } else {
- ajaxbox.focus();
- }
- });
+ }
+ });
+ }
// Make popup window close on escape (the dialog style is already taken care of)
$(document).keydown(function(e) {
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs
index 7338b1a..7a1fbbf 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs
@@ -40,6 +40,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.provider = new ProviderEndpointDescription(response.ProviderEndpoint, response.Version);
}
+ // Derived types of this are responsible to log an appropriate message for themselves.
+ if (Logger.OpenId.IsInfoEnabled && this.GetType() == typeof(PositiveAnonymousResponse)) {
+ Logger.OpenId.Info("Received anonymous (identity-less) positive assertion.");
+ }
+
Reporting.RecordEventOccurrence(this, response.ProviderEndpoint.AbsoluteUri);
}
@@ -130,6 +135,16 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#endregion
/// <summary>
+ /// Gets a value indicating whether trusted callback arguments are available.
+ /// </summary>
+ /// <remarks>
+ /// We use this internally to avoid logging a warning during a standard snapshot creation.
+ /// </remarks>
+ internal bool TrustedCallbackArgumentsAvailable {
+ get { return this.response.ReturnToParametersSignatureValidated; }
+ }
+
+ /// <summary>
/// Gets the positive extension-only message the Relying Party received that this instance wraps.
/// </summary>
protected internal IndirectSignedResponse Response {
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
index e809205..0fd034c 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
@@ -37,6 +37,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
null);
this.VerifyDiscoveryMatchesAssertion(relyingParty);
+
+ Logger.OpenId.InfoFormat("Received identity assertion for {0} via {1}.", this.ClaimedIdentifier, this.Provider.Uri);
}
#region IAuthenticationResponse Properties
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs
index 32c8af9..80b424a 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs
@@ -39,8 +39,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.FriendlyIdentifierForDisplay = copyFrom.FriendlyIdentifierForDisplay;
this.Status = copyFrom.Status;
this.Provider = copyFrom.Provider;
- this.callbackArguments = copyFrom.GetCallbackArguments();
this.untrustedCallbackArguments = copyFrom.GetUntrustedCallbackArguments();
+
+ // Do this special check to avoid logging a warning for trying to clone a dictionary.
+ var anonResponse = copyFrom as PositiveAnonymousResponse;
+ if (anonResponse == null || anonResponse.TrustedCallbackArgumentsAvailable) {
+ this.callbackArguments = copyFrom.GetCallbackArguments();
+ } else {
+ this.callbackArguments = EmptyDictionary<string, string>.Instance;
+ }
}
#region IAuthenticationResponse Members
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorOpenIdButton.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorOpenIdButton.cs
index 0b11695..15b6ca7 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorOpenIdButton.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorOpenIdButton.cs
@@ -5,7 +5,9 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OpenId.RelyingParty {
+ using System.ComponentModel;
using System.Diagnostics.Contracts;
+ using System.Drawing.Design;
using System.Web.UI;
using DotNetOpenAuth.Messaging;
@@ -25,6 +27,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// 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>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorProviderButton.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorProviderButton.cs
index 1d4dcf2..3a05287 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorProviderButton.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorProviderButton.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OpenId.RelyingParty {
using System.ComponentModel;
using System.Diagnostics.Contracts;
+ using System.Drawing.Design;
using System.Web.UI;
using DotNetOpenAuth.ComponentModel;
using DotNetOpenAuth.Messaging;
@@ -27,6 +28,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// 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>