summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-09-14 09:01:44 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2009-09-14 09:01:44 -0700
commit40d87d3af4dd5a9238fe838a5baf3b533b012359 (patch)
treed8bf9d7ba6f21e2af1e685b64249f8a91104f9d5
parentb83cf113f074c8b3887991413b8472056f2caa32 (diff)
parent07235e4d3aa03c3ea3597ad3f21e1cd265b81702 (diff)
downloadDotNetOpenAuth-40d87d3af4dd5a9238fe838a5baf3b533b012359.zip
DotNetOpenAuth-40d87d3af4dd5a9238fe838a5baf3b533b012359.tar.gz
DotNetOpenAuth-40d87d3af4dd5a9238fe838a5baf3b533b012359.tar.bz2
Merge branch 'v3.2'
Conflicts: src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs src/version.txt
-rw-r--r--doc/specs/ICAM_OpenID20Profile.pdfbin0 -> 687356 bytes
-rw-r--r--src/DotNetOpenAuth.sln1
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs15
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/AuthenticationRequest.cs15
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/HostProcessedRequest.cs8
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/IHostProcessedRequest.cs28
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs16
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/FailedAuthenticationResponse.cs36
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs14
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationResponse.cs51
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs34
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs59
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs45
15 files changed, 289 insertions, 37 deletions
diff --git a/doc/specs/ICAM_OpenID20Profile.pdf b/doc/specs/ICAM_OpenID20Profile.pdf
new file mode 100644
index 0000000..8b502b6
--- /dev/null
+++ b/doc/specs/ICAM_OpenID20Profile.pdf
Binary files differ
diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln
index 4c41496..f8d9b8f 100644
--- a/src/DotNetOpenAuth.sln
+++ b/src/DotNetOpenAuth.sln
@@ -16,6 +16,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Specs", "Specs", "{CD57219F-24F4-4136-8741-6063D0D7A031}"
ProjectSection(SolutionItems) = preProject
+ ..\doc\specs\ICAM_OpenID20Profile.pdf = ..\doc\specs\ICAM_OpenID20Profile.pdf
..\doc\specs\OAuth Core 1.0.htm = ..\doc\specs\OAuth Core 1.0.htm
..\doc\specs\OAuth Core 1.0a (Draft 3).htm = ..\doc\specs\OAuth Core 1.0a (Draft 3).htm
..\doc\specs\OpenID OAuth Extension.htm = ..\doc\specs\OpenID OAuth Extension.htm
diff --git a/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs b/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs
index b53e1f6..a500e3b 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs
@@ -37,6 +37,21 @@ namespace DotNetOpenAuth.OpenId.Provider {
this.positiveResponse = new IndirectSignedResponse(request);
}
+ #region HostProcessedRequest members
+
+ /// <summary>
+ /// Gets or sets the provider endpoint.
+ /// </summary>
+ /// <value>
+ /// The default value is the URL that the request came in on from the relying party.
+ /// </value>
+ public override Uri ProviderEndpoint {
+ get { return this.positiveResponse.ProviderEndpoint; }
+ set { this.positiveResponse.ProviderEndpoint = value; }
+ }
+
+ #endregion
+
#region IAnonymousRequest Members
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/Provider/AuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/Provider/AuthenticationRequest.cs
index 56e73da..a5d936b 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/AuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/AuthenticationRequest.cs
@@ -48,6 +48,21 @@ namespace DotNetOpenAuth.OpenId.Provider {
this.IsDelegatedIdentifier = this.ClaimedIdentifier != null && this.ClaimedIdentifier != this.LocalIdentifier;
}
+ #region HostProcessedRequest members
+
+ /// <summary>
+ /// Gets or sets the provider endpoint.
+ /// </summary>
+ /// <value>
+ /// The default value is the URL that the request came in on from the relying party.
+ /// </value>
+ public override Uri ProviderEndpoint {
+ get { return this.positiveResponse.ProviderEndpoint; }
+ set { this.positiveResponse.ProviderEndpoint = value; }
+ }
+
+ #endregion
+
/// <summary>
/// Gets a value indicating whether the response is ready to be created and sent.
/// </summary>
diff --git a/src/DotNetOpenAuth/OpenId/Provider/HostProcessedRequest.cs b/src/DotNetOpenAuth/OpenId/Provider/HostProcessedRequest.cs
index 6e61376..301f150 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/HostProcessedRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/HostProcessedRequest.cs
@@ -66,6 +66,14 @@ namespace DotNetOpenAuth.OpenId.Provider {
get { return this.RequestMessage.Realm; }
}
+ /// <summary>
+ /// Gets or sets the provider endpoint.
+ /// </summary>
+ /// <value>
+ /// The default value is the URL that the request came in on from the relying party.
+ /// </value>
+ public abstract Uri ProviderEndpoint { get; set; }
+
#endregion
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/Provider/IHostProcessedRequest.cs b/src/DotNetOpenAuth/OpenId/Provider/IHostProcessedRequest.cs
index 5256fdd..345ba52 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/IHostProcessedRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/IHostProcessedRequest.cs
@@ -33,6 +33,16 @@ namespace DotNetOpenAuth.OpenId.Provider {
bool Immediate { get; }
/// <summary>
+ /// Gets or sets the provider endpoint claimed in the positive assertion.
+ /// </summary>
+ /// <value>
+ /// The default value is the URL that the request came in on from the relying party.
+ /// This value MUST match the value for the OP Endpoint in the discovery results for the
+ /// claimed identifier being asserted in a positive response.
+ /// </value>
+ Uri ProviderEndpoint { get; set; }
+
+ /// <summary>
/// Attempts to perform relying party discovery of the return URL claimed by the Relying Party.
/// </summary>
/// <param name="provider">The OpenIdProvider that is performing the RP discovery.</param>
@@ -76,6 +86,24 @@ namespace DotNetOpenAuth.OpenId.Provider {
get { throw new System.NotImplementedException(); }
}
+ /// <summary>
+ /// Gets or sets the provider endpoint.
+ /// </summary>
+ /// <value>
+ /// The default value is the URL that the request came in on from the relying party.
+ /// </value>
+ Uri IHostProcessedRequest.ProviderEndpoint {
+ get {
+ Contract.Ensures(Contract.Result<Uri>() != null);
+ throw new NotImplementedException();
+ }
+
+ set {
+ Contract.Requires(value != null);
+ throw new NotImplementedException();
+ }
+ }
+
#endregion
#region IRequest Members
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
index ff7741a..d7345ac 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
@@ -189,17 +189,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="arguments">The arguments to add to the request's return_to URI.</param>
/// <remarks>
- /// <para>Note that these values are NOT protected against tampering in transit. No
- /// security-sensitive data should be stored using this method.</para>
+ /// <para>Note that these values are NOT protected against eavesdropping in transit. No
+ /// privacy-sensitive data should be stored using this method.</para>
/// <para>The values stored here can be retrieved using
- /// <see cref="IAuthenticationResponse.GetCallbackArguments"/>.</para>
+ /// <see cref="IAuthenticationResponse.GetCallbackArguments"/>, which will only return the value
+ /// if it hasn't been tampered with in transit.</para>
/// <para>Since the data set here is sent in the querystring of the request and some
/// servers place limits on the size of a request URL, this data should be kept relatively
/// small to ensure successful authentication. About 1.5KB is about all that should be stored.</para>
/// </remarks>
public void AddCallbackArguments(IDictionary<string, string> arguments) {
ErrorUtilities.VerifyArgumentNotNull(arguments, "arguments");
- ErrorUtilities.VerifyOperation(this.RelyingParty.CanSignCallbackArguments, OpenIdStrings.CallbackArgumentsRequireSecretStore, typeof(IAssociationStore<Uri>).Name, typeof(OpenIdRelyingParty).Name);
foreach (var pair in arguments) {
ErrorUtilities.VerifyArgument(!string.IsNullOrEmpty(pair.Key), MessagingStrings.UnexpectedNullOrEmptyKey);
@@ -215,10 +215,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <param name="key">The parameter name.</param>
/// <param name="value">The value of the argument.</param>
/// <remarks>
- /// <para>Note that these values are NOT protected against tampering in transit. No
- /// security-sensitive data should be stored using this method.</para>
+ /// <para>Note that these values are NOT protected against eavesdropping in transit. No
+ /// privacy-sensitive data should be stored using this method.</para>
/// <para>The value stored here can be retrieved using
- /// <see cref="IAuthenticationResponse.GetCallbackArgument"/>.</para>
+ /// <see cref="IAuthenticationResponse.GetCallbackArgument"/>, which will only return the value
+ /// if it hasn't been tampered with in transit.</para>
/// <para>Since the data set here is sent in the querystring of the request and some
/// servers place limits on the size of a request URL, this data should be kept relatively
/// small to ensure successful authentication. About 1.5KB is about all that should be stored.</para>
@@ -226,7 +227,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
public void AddCallbackArguments(string key, string value) {
ErrorUtilities.VerifyNonZeroLength(key, "key");
ErrorUtilities.VerifyArgumentNotNull(value, "value");
- ErrorUtilities.VerifyOperation(this.RelyingParty.CanSignCallbackArguments, OpenIdStrings.CallbackArgumentsRequireSecretStore, typeof(IAssociationStore<Uri>).Name, typeof(OpenIdRelyingParty).Name);
this.returnToArgs.Add(key, value);
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/FailedAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/FailedAuthenticationResponse.cs
index d94af14..45f7f54 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/FailedAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/FailedAuthenticationResponse.cs
@@ -128,7 +128,23 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <para>Note that these values are NOT protected against tampering in transit.</para>
/// </remarks>
public IDictionary<string, string> GetCallbackArguments() {
- return new Dictionary<string, string>();
+ return EmptyDictionary<string, string>.Instance;
+ }
+
+ /// <summary>
+ /// Gets all the callback arguments that were previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/> or as a natural part
+ /// of the return_to URL.
+ /// </summary>
+ /// <returns>A name-value dictionary. Never null.</returns>
+ /// <remarks>
+ /// Callback parameters are only available even if the RP is in stateless mode,
+ /// or the callback parameters are otherwise unverifiable as untampered with.
+ /// Therefore, use this method only when the callback argument is not to be
+ /// used to make a security-sensitive decision.
+ /// </remarks>
+ public IDictionary<string, string> GetUntrustedCallbackArguments() {
+ return EmptyDictionary<string, string>.Instance;
}
/// <summary>
@@ -150,6 +166,24 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Gets a callback argument's value that was previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.
+ /// </summary>
+ /// <param name="key">The name of the parameter whose value is sought.</param>
+ /// <returns>
+ /// The value of the argument, or null if the named parameter could not be found.
+ /// </returns>
+ /// <remarks>
+ /// Callback parameters are only available even if the RP is in stateless mode,
+ /// or the callback parameters are otherwise unverifiable as untampered with.
+ /// Therefore, use this method only when the callback argument is not to be
+ /// used to make a security-sensitive decision.
+ /// </remarks>
+ public string GetUntrustedCallbackArgument(string key) {
+ return null;
+ }
+
+ /// <summary>
/// Tries to get an OpenID extension that may be present in the response.
/// </summary>
/// <typeparam name="T">The type of extension to look for in the response message.</typeparam>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs
index 27daa46..5559899 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs
@@ -98,10 +98,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="arguments">The arguments to add to the request's return_to URI. Values must not be null.</param>
/// <remarks>
- /// <para>Note that these values are NOT protected against tampering in transit. No
- /// security-sensitive data should be stored using this method.</para>
+ /// <para>Note that these values are NOT protected against eavesdropping in transit. No
+ /// privacy-sensitive data should be stored using this method.</para>
/// <para>The values stored here can be retrieved using
- /// <see cref="IAuthenticationResponse.GetCallbackArguments"/>.</para>
+ /// <see cref="IAuthenticationResponse.GetCallbackArgument"/>, which will only return the value
+ /// if it can be verified as untampered with in transit.</para>
/// <para>Since the data set here is sent in the querystring of the request and some
/// servers place limits on the size of a request URL, this data should be kept relatively
/// small to ensure successful authentication. About 1.5KB is about all that should be stored.</para>
@@ -114,10 +115,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <param name="key">The parameter name.</param>
/// <param name="value">The value of the argument. Must not be null.</param>
/// <remarks>
- /// <para>Note that these values are NOT protected against tampering in transit. No
- /// security-sensitive data should be stored using this method.</para>
+ /// <para>Note that these values are NOT protected against eavesdropping in transit. No
+ /// privacy-sensitive data should be stored using this method.</para>
/// <para>The value stored here can be retrieved using
- /// <see cref="IAuthenticationResponse.GetCallbackArgument"/>.</para>
+ /// <see cref="IAuthenticationResponse.GetCallbackArgument"/>, which will only return the value
+ /// if it can be verified as untampered with in transit.</para>
/// <para>Since the data set here is sent in the querystring of the request and some
/// servers place limits on the size of a request URL, this data should be kept relatively
/// small to ensure successful authentication. About 1.5KB is about all that should be stored.</para>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationResponse.cs
index cc94de0..fd35a6b 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationResponse.cs
@@ -104,27 +104,60 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// The value of the argument, or null if the named parameter could not be found.
/// </returns>
/// <remarks>
- /// <para>This may return any argument on the querystring that came with the authentication response,
- /// which may include parameters not explicitly added using
- /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.</para>
- /// <para>Note that these values are NOT protected against tampering in transit.</para>
+ /// Callback parameters are only available if they are complete and untampered with
+ /// since the original request message (as proven by a signature).
+ /// If the relying party is operating in stateless mode <c>null</c> is always
+ /// returned since the callback arguments could not be signed to protect against
+ /// tampering.
/// </remarks>
string GetCallbackArgument(string key);
/// <summary>
+ /// Gets a callback argument's value that was previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.
+ /// </summary>
+ /// <param name="key">The name of the parameter whose value is sought.</param>
+ /// <returns>
+ /// The value of the argument, or null if the named parameter could not be found.
+ /// </returns>
+ /// <remarks>
+ /// Callback parameters are only available even if the RP is in stateless mode,
+ /// or the callback parameters are otherwise unverifiable as untampered with.
+ /// Therefore, use this method only when the callback argument is not to be
+ /// used to make a security-sensitive decision.
+ /// </remarks>
+ string GetUntrustedCallbackArgument(string key);
+
+ /// <summary>
+ /// Gets all the callback arguments that were previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/> or as a natural part
+ /// of the return_to URL.
+ /// </summary>
+ /// <returns>A name-value dictionary. Never null.</returns>
+ /// <remarks>
+ /// Callback parameters are only available if they are complete and untampered with
+ /// since the original request message (as proven by a signature).
+ /// If the relying party is operating in stateless mode an empty dictionary is always
+ /// returned since the callback arguments could not be signed to protect against
+ /// tampering.
+ /// </remarks>
+ [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Historically an expensive operation.")]
+ IDictionary<string, string> GetCallbackArguments();
+
+ /// <summary>
/// Gets all the callback arguments that were previously added using
/// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/> or as a natural part
/// of the return_to URL.
/// </summary>
/// <returns>A name-value dictionary. Never null.</returns>
/// <remarks>
- /// <para>This MAY return any argument on the querystring that came with the authentication response,
- /// which may include parameters not explicitly added using
- /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.</para>
- /// <para>Note that these values are NOT protected against tampering in transit.</para>
+ /// Callback parameters are only available even if the RP is in stateless mode,
+ /// or the callback parameters are otherwise unverifiable as untampered with.
+ /// Therefore, use this method only when the callback argument is not to be
+ /// used to make a security-sensitive decision.
/// </remarks>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Historically an expensive operation.")]
- IDictionary<string, string> GetCallbackArguments(); // TODO: change this to a property, and return a cached ReadOnlyDictionary
+ IDictionary<string, string> GetUntrustedCallbackArguments();
/// <summary>
/// Tries to get an OpenID extension that may be present in the response.
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
index e66ac28..5aa2e24 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
@@ -159,6 +159,24 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Gets a callback argument's value that was previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.
+ /// </summary>
+ /// <param name="key">The name of the parameter whose value is sought.</param>
+ /// <returns>
+ /// The value of the argument, or null if the named parameter could not be found.
+ /// </returns>
+ /// <remarks>
+ /// Callback parameters are only available even if the RP is in stateless mode,
+ /// or the callback parameters are otherwise unverifiable as untampered with.
+ /// Therefore, use this method only when the callback argument is not to be
+ /// used to make a security-sensitive decision.
+ /// </remarks>
+ public string GetUntrustedCallbackArgument(string key) {
+ return null;
+ }
+
+ /// <summary>
/// Gets all the callback arguments that were previously added using
/// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/> or as a natural part
/// of the return_to URL.
@@ -175,6 +193,22 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Gets all the callback arguments that were previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/> or as a natural part
+ /// of the return_to URL.
+ /// </summary>
+ /// <returns>A name-value dictionary. Never null.</returns>
+ /// <remarks>
+ /// Callback parameters are only available even if the RP is in stateless mode,
+ /// or the callback parameters are otherwise unverifiable as untampered with.
+ /// Therefore, use this method only when the callback argument is not to be
+ /// used to make a security-sensitive decision.
+ /// </remarks>
+ public IDictionary<string, string> GetUntrustedCallbackArguments() {
+ return EmptyDictionary<string, string>.Instance;
+ }
+
+ /// <summary>
/// Tries to get an OpenID extension that may be present in the response.
/// </summary>
/// <typeparam name="T">The type of extension to look for in the response message.</typeparam>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs
index a56f257..f3539cb 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs
@@ -635,7 +635,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
var response = this.RelyingParty.GetResponse();
if (response != null) {
- string persistentString = response.GetCallbackArgument(UsePersistentCookieCallbackKey);
+ string persistentString = response.GetUntrustedCallbackArgument(UsePersistentCookieCallbackKey);
bool persistentBool;
if (persistentString != null && bool.TryParse(persistentString, out persistentBool)) {
this.UsePersistentCookie = persistentBool;
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
index 68dd039..1cc69ec 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
@@ -623,7 +623,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
if (response == null) {
return;
}
- string persistentString = response.GetCallbackArgument(UsePersistentCookieCallbackKey);
+ string persistentString = response.GetUntrustedCallbackArgument(UsePersistentCookieCallbackKey);
if (persistentString != null) {
this.UsePersistentCookie = (LogOnPersistence)Enum.Parse(typeof(LogOnPersistence), persistentString);
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs
index 13eb1a2..baf30da 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs
@@ -154,13 +154,32 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </remarks>
public string GetCallbackArgument(string key) {
if (this.response.ReturnToParametersSignatureValidated) {
- return this.response.GetReturnToArgument(key);
+ return this.GetUntrustedCallbackArgument(key);
} else {
+ Logger.OpenId.WarnFormat(OpenIdStrings.CallbackArgumentsRequireSecretStore, typeof(IAssociationStore<Uri>).Name, typeof(OpenIdRelyingParty).Name);
return null;
}
}
/// <summary>
+ /// Gets a callback argument's value that was previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.
+ /// </summary>
+ /// <param name="key">The name of the parameter whose value is sought.</param>
+ /// <returns>
+ /// The value of the argument, or null if the named parameter could not be found.
+ /// </returns>
+ /// <remarks>
+ /// Callback parameters are only available even if the RP is in stateless mode,
+ /// or the callback parameters are otherwise unverifiable as untampered with.
+ /// Therefore, use this method only when the callback argument is not to be
+ /// used to make a security-sensitive decision.
+ /// </remarks>
+ public string GetUntrustedCallbackArgument(string key) {
+ return this.response.GetReturnToArgument(key);
+ }
+
+ /// <summary>
/// Gets all the callback arguments that were previously added using
/// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/> or as a natural part
/// of the return_to URL.
@@ -175,22 +194,40 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </remarks>
public IDictionary<string, string> GetCallbackArguments() {
if (this.response.ReturnToParametersSignatureValidated) {
- var args = new Dictionary<string, string>();
-
- // Return all the return_to arguments, except for the OpenID-supporting ones.
- // The only arguments that should be returned here are the ones that the host
- // web site adds explicitly.
- foreach (string key in this.response.GetReturnToParameterNames().Where(key => !OpenIdRelyingParty.IsOpenIdSupportingParameter(key))) {
- args[key] = this.response.GetReturnToArgument(key);
- }
-
- return args;
+ return this.GetUntrustedCallbackArguments();
} else {
+ Logger.OpenId.WarnFormat(OpenIdStrings.CallbackArgumentsRequireSecretStore, typeof(IAssociationStore<Uri>).Name, typeof(OpenIdRelyingParty).Name);
return EmptyDictionary<string, string>.Instance;
}
}
/// <summary>
+ /// Gets all the callback arguments that were previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/> or as a natural part
+ /// of the return_to URL.
+ /// </summary>
+ /// <returns>A name-value dictionary. Never null.</returns>
+ /// <remarks>
+ /// Callback parameters are only available if they are complete and untampered with
+ /// since the original request message (as proven by a signature).
+ /// If the relying party is operating in stateless mode an empty dictionary is always
+ /// returned since the callback arguments could not be signed to protect against
+ /// tampering.
+ /// </remarks>
+ public IDictionary<string, string> GetUntrustedCallbackArguments() {
+ var args = new Dictionary<string, string>();
+
+ // Return all the return_to arguments, except for the OpenID-supporting ones.
+ // The only arguments that should be returned here are the ones that the host
+ // web site adds explicitly.
+ foreach (string key in this.response.GetReturnToParameterNames().Where(key => !OpenIdRelyingParty.IsOpenIdSupportingParameter(key))) {
+ args[key] = this.response.GetReturnToArgument(key);
+ }
+
+ return args;
+ }
+
+ /// <summary>
/// Tries to get an OpenID extension that may be present in the response.
/// </summary>
/// <typeparam name="T">The type of extension to look for in the response message.</typeparam>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs
index 04a403c..e5bd22f 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs
@@ -23,6 +23,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private IDictionary<string, string> callbackArguments;
/// <summary>
+ /// The untrusted callback arguments that came with the authentication response.
+ /// </summary>
+ private IDictionary<string, string> untrustedCallbackArguments;
+
+ /// <summary>
/// Initializes a new instance of the <see cref="PositiveAuthenticationResponseSnapshot"/> class.
/// </summary>
/// <param name="copyFrom">The authentication response to copy from.</param>
@@ -34,6 +39,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.Status = copyFrom.Status;
this.Provider = copyFrom.Provider;
this.callbackArguments = copyFrom.GetCallbackArguments();
+ this.untrustedCallbackArguments = copyFrom.GetUntrustedCallbackArguments();
}
#region IAuthenticationResponse Members
@@ -229,6 +235,23 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Gets all the callback arguments that were previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/> or as a natural part
+ /// of the return_to URL.
+ /// </summary>
+ /// <returns>A name-value dictionary. Never null.</returns>
+ /// <remarks>
+ /// Callback parameters are only available even if the RP is in stateless mode,
+ /// or the callback parameters are otherwise unverifiable as untampered with.
+ /// Therefore, use this method only when the callback argument is not to be
+ /// used to make a security-sensitive decision.
+ /// </remarks>
+ public IDictionary<string, string> GetUntrustedCallbackArguments() {
+ // Return a copy so that the caller cannot change the contents.
+ return new Dictionary<string, string>(this.untrustedCallbackArguments);
+ }
+
+ /// <summary>
/// Gets a callback argument's value that was previously added using
/// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.
/// </summary>
@@ -250,6 +273,28 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
return value;
}
+ /// <summary>
+ /// Gets a callback argument's value that was previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.
+ /// </summary>
+ /// <param name="key">The name of the parameter whose value is sought.</param>
+ /// <returns>
+ /// The value of the argument, or null if the named parameter could not be found.
+ /// </returns>
+ /// <remarks>
+ /// Callback parameters are only available even if the RP is in stateless mode,
+ /// or the callback parameters are otherwise unverifiable as untampered with.
+ /// Therefore, use this method only when the callback argument is not to be
+ /// used to make a security-sensitive decision.
+ /// </remarks>
+ public string GetUntrustedCallbackArgument(string key) {
+ ErrorUtilities.VerifyArgumentNotNull(key, "key");
+
+ string value;
+ this.untrustedCallbackArguments.TryGetValue(key, out value);
+ return value;
+ }
+
#endregion
}
}