summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj2
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/TestBadChannel.cs4
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/AssociationsTests.cs (renamed from src/DotNetOpenAuth.Test/OpenId/AssociationsTests.cs)3
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj3
-rw-r--r--src/DotNetOpenAuth/Messaging/BinaryDataBagFormatter.cs43
-rw-r--r--src/DotNetOpenAuth/Messaging/DataBagFormatterBase.cs85
-rw-r--r--src/DotNetOpenAuth/Messaging/IStreamSerializingDataBag.cs55
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs47
-rw-r--r--src/DotNetOpenAuth/Messaging/UriStyleMessageFormatter.cs14
-rw-r--r--src/DotNetOpenAuth/OpenId/Association.cs3
-rw-r--r--src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/ChannelElements/SigningBindingElement.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/HmacShaAssociation.cs5
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs5
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/AssociateRequest.cs5
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/AssociateSuccessfulResponse.cs14
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/AssociateUnencryptedResponse.cs13
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationResponse.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/AssociationDataBag.cs41
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/ProviderAssociationStore.cs42
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/AssociationMemoryStore.cs1
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/Associations.cs (renamed from src/DotNetOpenAuth/OpenId/Associations.cs)2
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/IAssociationStore.cs3
24 files changed, 278 insertions, 128 deletions
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
index 941857d..9bae939 100644
--- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
+++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
@@ -243,7 +243,7 @@
<Compile Include="OAuth\ProtocolTests.cs" />
<Compile Include="OAuth\ServiceProviderDescriptionTests.cs" />
<Compile Include="OAuth\ServiceProviderTests.cs" />
- <Compile Include="OpenId\AssociationsTests.cs" />
+ <Compile Include="OpenId\RelyingParty\AssociationsTests.cs" />
<Compile Include="OpenId\AssociationTests.cs" />
<Compile Include="OpenId\AuthenticationTests.cs" />
<Compile Include="OpenId\ChannelElements\ExtensionsBindingElementTests.cs" />
diff --git a/src/DotNetOpenAuth.Test/Mocks/TestBadChannel.cs b/src/DotNetOpenAuth.Test/Mocks/TestBadChannel.cs
index 439acbb..515e69e 100644
--- a/src/DotNetOpenAuth.Test/Mocks/TestBadChannel.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/TestBadChannel.cs
@@ -17,8 +17,8 @@ namespace DotNetOpenAuth.Test.Mocks {
: base(badConstructorParam ? null : new TestMessageFactory()) {
}
- internal new void Create301RedirectResponse(IDirectedProtocolMessage message, IDictionary<string, string> fields) {
- base.Create301RedirectResponse(message, fields);
+ internal new void Create301RedirectResponse(IDirectedProtocolMessage message, IDictionary<string, string> fields, bool payloadInFragment = false) {
+ base.Create301RedirectResponse(message, fields, payloadInFragment);
}
internal new void CreateFormPostResponse(IDirectedProtocolMessage message, IDictionary<string, string> fields) {
diff --git a/src/DotNetOpenAuth.Test/OpenId/AssociationsTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AssociationsTests.cs
index b3d7e4d..531fb45 100644
--- a/src/DotNetOpenAuth.Test/OpenId/AssociationsTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AssociationsTests.cs
@@ -4,13 +4,14 @@
// </copyright>
//-----------------------------------------------------------------------
-namespace DotNetOpenAuth.Test.OpenId {
+namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.RelyingParty;
using NUnit.Framework;
[TestFixture]
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index 70b079c..ed3f63f 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -341,6 +341,7 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="Messaging\IncomingWebResponseContract.cs" />
<Compile Include="Messaging\IProtocolMessageWithExtensions.cs" />
<Compile Include="Messaging\InternalErrorException.cs" />
+ <Compile Include="Messaging\IStreamSerializingDataBag.cs" />
<Compile Include="Messaging\KeyedCollectionDelegate.cs" />
<Compile Include="Messaging\MultipartPostPart.cs" />
<Compile Include="Messaging\NetworkDirectWebResponse.cs" />
@@ -498,7 +499,7 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="OpenId\RelyingParty\AssociationMemoryStore.cs" />
<Compile Include="OpenId\Provider\ProviderAssociationStore.cs" />
<Compile Include="OpenId\RelyingParty\IAssociationStore.cs" />
- <Compile Include="OpenId\Associations.cs" />
+ <Compile Include="OpenId\RelyingParty\Associations.cs" />
<Compile Include="OpenId\Behaviors\AXFetchAsSregTransform.cs" />
<Compile Include="OpenId\Behaviors\BehaviorStrings.Designer.cs">
<AutoGen>True</AutoGen>
diff --git a/src/DotNetOpenAuth/Messaging/BinaryDataBagFormatter.cs b/src/DotNetOpenAuth/Messaging/BinaryDataBagFormatter.cs
index 0dfd8aa..08c1219 100644
--- a/src/DotNetOpenAuth/Messaging/BinaryDataBagFormatter.cs
+++ b/src/DotNetOpenAuth/Messaging/BinaryDataBagFormatter.cs
@@ -14,37 +14,18 @@ namespace DotNetOpenAuth.Messaging {
using System.Text;
using DotNetOpenAuth.Messaging.Bindings;
- [ContractClass(typeof(IStreamSerializingMessageContract))]
- internal interface IStreamSerializingMessage {
- void Serialize(Stream stream);
-
- void Deserialize(Stream stream);
- }
-
- [ContractClassFor(typeof(IStreamSerializingMessage))]
- internal abstract class IStreamSerializingMessageContract : IStreamSerializingMessage {
- void IStreamSerializingMessage.Serialize(Stream stream) {
- Contract.Requires(stream != null);
- Contract.Requires(stream.CanWrite);
- throw new NotImplementedException();
- }
-
- void IStreamSerializingMessage.Deserialize(Stream stream) {
- Contract.Requires(stream != null);
- Contract.Requires(stream.CanRead);
- throw new NotImplementedException();
- }
- }
-
-
- internal class BinaryDataBagFormatter<T> : DataBagFormatterBase<T> where T : DataBag, IStreamSerializingMessage, new() {
+ /// <summary>
+ /// A compact binary <see cref="DataBag"/> serialization class.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="DataBag"/>-derived type to serialize/deserialize.</typeparam>
+ internal class BinaryDataBagFormatter<T> : DataBagFormatterBase<T> where T : DataBag, IStreamSerializingDataBag, new() {
/// <summary>
/// Initializes a new instance of the <see cref="UriStyleMessageFormatter&lt;T&gt;"/> class.
/// </summary>
/// <param name="signingKey">The crypto service provider with the asymmetric key to use for signing or verifying the token.</param>
/// <param name="encryptingKey">The crypto service provider with the asymmetric key to use for encrypting or decrypting the token.</param>
/// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
- /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.</param>
+ /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <paramref name="decodeOnceOnly"/> is <c>true</c>.</param>
/// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
protected internal BinaryDataBagFormatter(RSACryptoServiceProvider signingKey = null, RSACryptoServiceProvider encryptingKey = null, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null)
: base(signingKey, encryptingKey, compressed, maximumAge, decodeOnceOnly) {
@@ -57,19 +38,29 @@ namespace DotNetOpenAuth.Messaging {
/// <param name="signed">A value indicating whether the data in this instance will be protected against tampering.</param>
/// <param name="encrypted">A value indicating whether the data in this instance will be protected against eavesdropping.</param>
/// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
- /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.</param>
+ /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <paramref name="decodeOnceOnly"/> is <c>true</c>.</param>
/// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
protected internal BinaryDataBagFormatter(byte[] symmetricSecret = null, bool signed = false, bool encrypted = false, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null)
: base(symmetricSecret, signed, encrypted, compressed, maximumAge, decodeOnceOnly) {
Contract.Requires<ArgumentException>(symmetricSecret != null || (!signed && !encrypted), "A secret is required when signing or encrypting is required.");
}
+ /// <summary>
+ /// Serializes the <see cref="DataBag"/> instance to a buffer.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ /// <returns>The buffer containing the serialized data.</returns>
protected override byte[] SerializeCore(T message) {
var stream = new MemoryStream();
message.Serialize(stream);
return stream.ToArray();
}
+ /// <summary>
+ /// Deserializes the <see cref="DataBag"/> instance from a buffer.
+ /// </summary>
+ /// <param name="message">The message instance to initialize with data from the buffer.</param>
+ /// <param name="data">The data buffer.</param>
protected override void DeserializeCore(T message, byte[] data) {
var stream = new MemoryStream(data);
message.Deserialize(stream);
diff --git a/src/DotNetOpenAuth/Messaging/DataBagFormatterBase.cs b/src/DotNetOpenAuth/Messaging/DataBagFormatterBase.cs
index 89d69d3..98f5e8c 100644
--- a/src/DotNetOpenAuth/Messaging/DataBagFormatterBase.cs
+++ b/src/DotNetOpenAuth/Messaging/DataBagFormatterBase.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.Messaging {
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
+ using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
@@ -15,7 +16,6 @@ namespace DotNetOpenAuth.Messaging {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
using DotNetOpenAuth.Messaging.Reflection;
- using System.IO;
/// <summary>
/// A serializer for <see cref="DataBag"/>-derived types
@@ -23,14 +23,14 @@ namespace DotNetOpenAuth.Messaging {
/// <typeparam name="T">The DataBag-derived type that is to be serialized/deserialized.</typeparam>
internal abstract class DataBagFormatterBase<T> : IDataBagFormatter<T> where T : DataBag, new() {
/// <summary>
- /// The length of the nonce to include in tokens that can be decoded once only.
+ /// The message description cache to use for data bag types.
/// </summary>
- private const int NonceLength = 6;
+ protected static readonly MessageDescriptionCollection MessageDescriptions = new MessageDescriptionCollection();
/// <summary>
- /// The message description cache to use for data bag types.
+ /// The length of the nonce to include in tokens that can be decoded once only.
/// </summary>
- protected static readonly MessageDescriptionCollection MessageDescriptions = new MessageDescriptionCollection();
+ private const int NonceLength = 6;
/// <summary>
/// The symmetric secret used for signing/encryption of verification codes and refresh tokens.
@@ -85,29 +85,10 @@ namespace DotNetOpenAuth.Messaging {
/// <summary>
/// Initializes a new instance of the <see cref="UriStyleMessageFormatter&lt;T&gt;"/> class.
/// </summary>
- /// <param name="signed">A value indicating whether the data in this instance will be protected against tampering.</param>
- /// <param name="encrypted">A value indicating whether the data in this instance will be protected against eavesdropping.</param>
- /// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
- /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.</param>
- /// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
- private DataBagFormatterBase(bool signed = false, bool encrypted = false, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null) {
- Contract.Requires<ArgumentException>(signed || decodeOnceOnly == null, "A signature must be applied if this data is meant to be decoded only once.");
- Contract.Requires<ArgumentException>(maximumAge.HasValue || decodeOnceOnly == null, "A maximum age must be given if a message can only be decoded once.");
-
- this.signed = signed;
- this.maximumAge = maximumAge;
- this.decodeOnceOnly = decodeOnceOnly;
- this.encrypted = encrypted;
- this.compressed = compressed;
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="UriStyleMessageFormatter&lt;T&gt;"/> class.
- /// </summary>
/// <param name="signingKey">The crypto service provider with the asymmetric key to use for signing or verifying the token.</param>
/// <param name="encryptingKey">The crypto service provider with the asymmetric key to use for encrypting or decrypting the token.</param>
/// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
- /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.</param>
+ /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <paramref name="decodeOnceOnly"/> is <c>true</c>.</param>
/// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
protected DataBagFormatterBase(RSACryptoServiceProvider signingKey = null, RSACryptoServiceProvider encryptingKey = null, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null)
: this(signingKey != null, encryptingKey != null, compressed, maximumAge, decodeOnceOnly) {
@@ -123,7 +104,7 @@ namespace DotNetOpenAuth.Messaging {
/// <param name="signed">A value indicating whether the data in this instance will be protected against tampering.</param>
/// <param name="encrypted">A value indicating whether the data in this instance will be protected against eavesdropping.</param>
/// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
- /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.</param>
+ /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <paramref name="decodeOnceOnly"/> is <c>true</c>.</param>
/// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
protected DataBagFormatterBase(byte[] symmetricSecret = null, bool signed = false, bool encrypted = false, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null)
: this(signed, encrypted, compressed, maximumAge, decodeOnceOnly) {
@@ -137,7 +118,26 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
- /// Serializes the specified message.
+ /// Initializes a new instance of the <see cref="UriStyleMessageFormatter&lt;T&gt;"/> class.
+ /// </summary>
+ /// <param name="signed">A value indicating whether the data in this instance will be protected against tampering.</param>
+ /// <param name="encrypted">A value indicating whether the data in this instance will be protected against eavesdropping.</param>
+ /// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
+ /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <paramref name="decodeOnceOnly"/> is <c>true</c>.</param>
+ /// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
+ private DataBagFormatterBase(bool signed = false, bool encrypted = false, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null) {
+ Contract.Requires<ArgumentException>(signed || decodeOnceOnly == null, "A signature must be applied if this data is meant to be decoded only once.");
+ Contract.Requires<ArgumentException>(maximumAge.HasValue || decodeOnceOnly == null, "A maximum age must be given if a message can only be decoded once.");
+
+ this.signed = signed;
+ this.maximumAge = maximumAge;
+ this.decodeOnceOnly = decodeOnceOnly;
+ this.encrypted = encrypted;
+ this.compressed = compressed;
+ }
+
+ /// <summary>
+ /// Serializes the specified message, including compression, encryption, signing, and nonce handling where applicable.
/// </summary>
/// <param name="message">The message to serialize. Must not be null.</param>
/// <returns>A non-null, non-empty value.</returns>
@@ -175,12 +175,8 @@ namespace DotNetOpenAuth.Messaging {
return Convert.ToBase64String(finalStream.ToArray());
}
- protected abstract byte[] SerializeCore(T message);
-
- protected abstract void DeserializeCore(T message, byte[] data);
-
/// <summary>
- /// Deserializes a <see cref="DataBag"/>.
+ /// Deserializes a <see cref="DataBag"/>, including decompression, decryption, signature and nonce validation where applicable.
/// </summary>
/// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be nulll.</param>
/// <param name="value">The serialized form of the <see cref="DataBag"/> to deserialize. Must not be null or empty.</param>
@@ -235,11 +231,26 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Serializes the <see cref="DataBag"/> instance to a buffer.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ /// <returns>The buffer containing the serialized data.</returns>
+ protected abstract byte[] SerializeCore(T message);
+
+ /// <summary>
+ /// Deserializes the <see cref="DataBag"/> instance from a buffer.
+ /// </summary>
+ /// <param name="message">The message instance to initialize with data from the buffer.</param>
+ /// <param name="data">The data buffer.</param>
+ protected abstract void DeserializeCore(T message, byte[] data);
+
+ /// <summary>
/// Determines whether the signature on this instance is valid.
/// </summary>
- /// <param name="message">The message whose signature is to be checked.</param>
+ /// <param name="signedData">The signed data.</param>
+ /// <param name="signature">The signature.</param>
/// <returns>
- /// <c>true</c> if the signature is valid; otherwise, <c>false</c>.
+ /// <c>true</c> if the signature is valid; otherwise, <c>false</c>.
/// </returns>
private bool IsSignatureValid(byte[] signedData, byte[] signature) {
Contract.Requires<ArgumentNullException>(signedData != null, "message");
@@ -255,8 +266,10 @@ namespace DotNetOpenAuth.Messaging {
/// <summary>
/// Calculates the signature for the data in this verification code.
/// </summary>
- /// <param name="message">The message whose signature is to be calculated.</param>
- /// <returns>The calculated signature.</returns>
+ /// <param name="bytesToSign">The bytes to sign.</param>
+ /// <returns>
+ /// The calculated signature.
+ /// </returns>
private byte[] CalculateSignature(byte[] bytesToSign) {
Contract.Requires<ArgumentNullException>(bytesToSign != null, "bytesToSign");
Contract.Requires<InvalidOperationException>(this.asymmetricSigning != null || this.symmetricHasher != null);
diff --git a/src/DotNetOpenAuth/Messaging/IStreamSerializingDataBag.cs b/src/DotNetOpenAuth/Messaging/IStreamSerializingDataBag.cs
new file mode 100644
index 0000000..2003f9e
--- /dev/null
+++ b/src/DotNetOpenAuth/Messaging/IStreamSerializingDataBag.cs
@@ -0,0 +1,55 @@
+//-----------------------------------------------------------------------
+// <copyright file="IStreamSerializingDataBag.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Messaging {
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.IO;
+
+ /// <summary>
+ /// An interface implemented by <see cref="DataBag"/>-derived types that support binary serialization.
+ /// </summary>
+ [ContractClass(typeof(IStreamSerializingDataBaContract))]
+ internal interface IStreamSerializingDataBag {
+ /// <summary>
+ /// Serializes the instance to the specified stream.
+ /// </summary>
+ /// <param name="stream">The stream.</param>
+ void Serialize(Stream stream);
+
+ /// <summary>
+ /// Initializes the fields on this instance from the specified stream.
+ /// </summary>
+ /// <param name="stream">The stream.</param>
+ void Deserialize(Stream stream);
+ }
+
+ /// <summary>
+ /// Code Contract for the <see cref="IStreamSerializingDataBag"/> interface.
+ /// </summary>
+ [ContractClassFor(typeof(IStreamSerializingDataBag))]
+ internal abstract class IStreamSerializingDataBaContract : IStreamSerializingDataBag {
+ /// <summary>
+ /// Serializes the instance to the specified stream.
+ /// </summary>
+ /// <param name="stream">The stream.</param>
+ void IStreamSerializingDataBag.Serialize(Stream stream) {
+ Contract.Requires(stream != null);
+ Contract.Requires(stream.CanWrite);
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Initializes the fields on this instance from the specified stream.
+ /// </summary>
+ /// <param name="stream">The stream.</param>
+ void IStreamSerializingDataBag.Deserialize(Stream stream) {
+ Contract.Requires(stream != null);
+ Contract.Requires(stream.CanRead);
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs b/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
index ea33f49..aa7f5b7 100644
--- a/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
+++ b/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
@@ -252,14 +252,6 @@ namespace DotNetOpenAuth.Messaging.Reflection {
}
}
- internal void SetValueAsObject(IMessage message, object value) {
- if (this.property != null) {
- this.property.SetValue(message, value, null);
- } else {
- this.field.SetValue(message, value);
- }
- }
-
/// <summary>
/// Gets the normalized form of a value of a member of a given message.
/// Used in serialization.
@@ -305,19 +297,6 @@ namespace DotNetOpenAuth.Messaging.Reflection {
}
/// <summary>
- /// Gets the value of the message part, without converting it to/from a string.
- /// </summary>
- /// <param name="message">The message instance to read from.</param>
- /// <returns>The value of the member.</returns>
- internal object GetValueAsObject(IMessage message) {
- if (this.property != null) {
- return this.property.GetValue(message, null);
- } else {
- return this.field.GetValue(message);
- }
- }
-
- /// <summary>
/// Figures out the CLR default value for a given type.
/// </summary>
/// <param name="type">The type whose default value is being sought.</param>
@@ -391,6 +370,32 @@ namespace DotNetOpenAuth.Messaging.Reflection {
}
/// <summary>
+ /// Gets the value of the message part, without converting it to/from a string.
+ /// </summary>
+ /// <param name="message">The message instance to read from.</param>
+ /// <returns>The value of the member.</returns>
+ private object GetValueAsObject(IMessage message) {
+ if (this.property != null) {
+ return this.property.GetValue(message, null);
+ } else {
+ return this.field.GetValue(message);
+ }
+ }
+
+ /// <summary>
+ /// Sets the value of a message part directly with a given value.
+ /// </summary>
+ /// <param name="message">The message instance to read from.</param>
+ /// <param name="value">The value to set on the this part.</param>
+ private void SetValueAsObject(IMessage message, object value) {
+ if (this.property != null) {
+ this.property.SetValue(message, value, null);
+ } else {
+ this.field.SetValue(message, value);
+ }
+ }
+
+ /// <summary>
/// Converts a string representation of the member's value to the appropriate type.
/// </summary>
/// <param name="value">The string representation of the member's value.</param>
diff --git a/src/DotNetOpenAuth/Messaging/UriStyleMessageFormatter.cs b/src/DotNetOpenAuth/Messaging/UriStyleMessageFormatter.cs
index 24f696f..b435f1b 100644
--- a/src/DotNetOpenAuth/Messaging/UriStyleMessageFormatter.cs
+++ b/src/DotNetOpenAuth/Messaging/UriStyleMessageFormatter.cs
@@ -27,7 +27,7 @@ namespace DotNetOpenAuth.Messaging {
/// <param name="signingKey">The crypto service provider with the asymmetric key to use for signing or verifying the token.</param>
/// <param name="encryptingKey">The crypto service provider with the asymmetric key to use for encrypting or decrypting the token.</param>
/// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
- /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.</param>
+ /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <paramref name="decodeOnceOnly"/> is <c>true</c>.</param>
/// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
protected internal UriStyleMessageFormatter(RSACryptoServiceProvider signingKey = null, RSACryptoServiceProvider encryptingKey = null, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null)
: base(signingKey, encryptingKey, compressed, maximumAge, decodeOnceOnly) {
@@ -40,19 +40,29 @@ namespace DotNetOpenAuth.Messaging {
/// <param name="signed">A value indicating whether the data in this instance will be protected against tampering.</param>
/// <param name="encrypted">A value indicating whether the data in this instance will be protected against eavesdropping.</param>
/// <param name="compressed">A value indicating whether the data in this instance will be GZip'd.</param>
- /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <see cref="decodeOnceOnly"/> is <c>true</c>.</param>
+ /// <param name="maximumAge">The maximum age of a token that can be decoded; useful only when <paramref name="decodeOnceOnly"/> is <c>true</c>.</param>
/// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param>
protected internal UriStyleMessageFormatter(byte[] symmetricSecret = null, bool signed = false, bool encrypted = false, bool compressed = false, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null)
: base(symmetricSecret, signed, encrypted, compressed, maximumAge, decodeOnceOnly) {
Contract.Requires<ArgumentException>(symmetricSecret != null || (!signed && !encrypted), "A secret is required when signing or encrypting is required.");
}
+ /// <summary>
+ /// Serializes the <see cref="DataBag"/> instance to a buffer.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ /// <returns>The buffer containing the serialized data.</returns>
protected override byte[] SerializeCore(T message) {
var fields = MessageSerializer.Get(message.GetType()).Serialize(MessageDescriptions.GetAccessor(message));
string value = MessagingUtilities.CreateQueryString(fields);
return Encoding.UTF8.GetBytes(value);
}
+ /// <summary>
+ /// Deserializes the <see cref="DataBag"/> instance from a buffer.
+ /// </summary>
+ /// <param name="message">The message instance to initialize with data from the buffer.</param>
+ /// <param name="data">The data buffer.</param>
protected override void DeserializeCore(T message, byte[] data) {
string value = Encoding.UTF8.GetString(data);
diff --git a/src/DotNetOpenAuth/OpenId/Association.cs b/src/DotNetOpenAuth/OpenId/Association.cs
index 5c2a09e..0a59a7d 100644
--- a/src/DotNetOpenAuth/OpenId/Association.cs
+++ b/src/DotNetOpenAuth/OpenId/Association.cs
@@ -14,6 +14,7 @@ namespace DotNetOpenAuth.OpenId {
using System.Text;
using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.RelyingParty;
/// <summary>
/// Stores a secret used in signing and verifying messages.
@@ -159,7 +160,7 @@ namespace DotNetOpenAuth.OpenId {
/// <returns>
/// The newly dehydrated <see cref="Association"/>, which can be returned
/// from a custom association store's
- /// <see cref="IAssociationStore&lt;TKey&gt;.GetAssociation(TKey, SecuritySettings)"/> method.
+ /// <see cref="IAssociationStore.GetAssociation(Uri, SecuritySettings)"/> method.
/// </returns>
public static Association Deserialize(string handle, DateTime expiresUtc, byte[] privateData) {
Contract.Requires<ArgumentNullException>(!String.IsNullOrEmpty(handle));
diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs
index 049ea3a..5350e6c 100644
--- a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs
+++ b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs
@@ -58,6 +58,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Initializes a new instance of the <see cref="OpenIdChannel"/> class
/// for use by a Provider.
/// </summary>
+ /// <param name="associationStore">The OpenID Provider's association store or handle encoder.</param>
/// <param name="nonceStore">The nonce store to use.</param>
/// <param name="securitySettings">The security settings.</param>
internal OpenIdChannel(ProviderAssociationStore associationStore, INonceStore nonceStore, ProviderSecuritySettings securitySettings)
@@ -357,10 +358,9 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// <summary>
/// Initializes the binding elements.
/// </summary>
- /// <param name="associationStore">The association store.</param>
+ /// <param name="associationStore">The OpenID Provider's association store or handle encoder.</param>
/// <param name="nonceStore">The nonce store to use.</param>
/// <param name="securitySettings">The security settings to apply. Must be an instance of either <see cref="RelyingPartySecuritySettings"/> or <see cref="ProviderSecuritySettings"/>.</param>
- /// <param name="nonVerifying">A value indicating whether the channel is set up with no functional security binding elements.</param>
/// <returns>
/// An array of binding elements which may be used to construct the channel.
/// </returns>
diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/SigningBindingElement.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/SigningBindingElement.cs
index be64d82..444098e 100644
--- a/src/DotNetOpenAuth/OpenId/ChannelElements/SigningBindingElement.cs
+++ b/src/DotNetOpenAuth/OpenId/ChannelElements/SigningBindingElement.cs
@@ -292,9 +292,9 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
MessageDescription description = this.Channel.MessageDescriptions.Get(signedMessage);
var signedParts = from part in description.Mapping.Values
- where (part.RequiredProtection & System.Net.Security.ProtectionLevel.Sign) != 0
- && part.GetValue(signedMessage) != null
- select part.Name;
+ where (part.RequiredProtection & System.Net.Security.ProtectionLevel.Sign) != 0
+ && part.GetValue(signedMessage) != null
+ select part.Name;
string prefix = Protocol.V20.openid.Prefix;
ErrorUtilities.VerifyInternal(signedParts.All(name => name.StartsWith(prefix, StringComparison.Ordinal)), "All signed message parts must start with 'openid.'.");
diff --git a/src/DotNetOpenAuth/OpenId/HmacShaAssociation.cs b/src/DotNetOpenAuth/OpenId/HmacShaAssociation.cs
index 0108566..4fa88e9 100644
--- a/src/DotNetOpenAuth/OpenId/HmacShaAssociation.cs
+++ b/src/DotNetOpenAuth/OpenId/HmacShaAssociation.cs
@@ -144,8 +144,11 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="associationType">Type of the association (i.e. HMAC-SHA1 or HMAC-SHA256)</param>
/// <param name="associationUse">A value indicating whether the new association will be used privately by the Provider for "dumb mode" authentication
/// or shared with the Relying Party for "smart mode" authentication.</param>
+ /// <param name="associationStore">The Provider's association store.</param>
/// <param name="securitySettings">The security settings of the Provider.</param>
- /// <returns>The newly created association.</returns>
+ /// <returns>
+ /// The newly created association.
+ /// </returns>
/// <remarks>
/// The new association is NOT automatically put into an association store. This must be done by the caller.
/// </remarks>
diff --git a/src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs
index 86e2d8c..d0d9c08 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs
@@ -66,8 +66,11 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// Creates the association at the provider side after the association request has been received.
/// </summary>
/// <param name="request">The association request.</param>
+ /// <param name="associationStore">The OpenID Provider's association store or handle encoder.</param>
/// <param name="securitySettings">The security settings of the Provider.</param>
- /// <returns>The newly created association.</returns>
+ /// <returns>
+ /// The newly created association.
+ /// </returns>
/// <remarks>
/// The response message is updated to include the details of the created association by this method,
/// but the resulting association is <i>not</i> added to the association store and must be done by the caller.
diff --git a/src/DotNetOpenAuth/OpenId/Messages/AssociateRequest.cs b/src/DotNetOpenAuth/OpenId/Messages/AssociateRequest.cs
index 937c7ff..ea7e3c6 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/AssociateRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/AssociateRequest.cs
@@ -129,14 +129,15 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// <summary>
/// Creates a Provider's response to an incoming association request.
/// </summary>
+ /// <param name="associationStore">The association store.</param>
/// <param name="securitySettings">The security settings on the Provider.</param>
/// <returns>
/// The appropriate association response that is ready to be sent back to the Relying Party.
/// </returns>
/// <remarks>
- /// <para>If an association is created, it will be automatically be added to the provided
+ /// <para>If an association is created, it will be automatically be added to the provided
/// association store.</para>
- /// <para>Successful association response messages will derive from <see cref="AssociateSuccessfulResponse"/>.
+ /// <para>Successful association response messages will derive from <see cref="AssociateSuccessfulResponse"/>.
/// Failed association response messages will derive from <see cref="AssociateUnsuccessfulResponse"/>.</para>
/// </remarks>
internal IProtocolMessage CreateResponse(ProviderAssociationStore associationStore, ProviderSecuritySettings securitySettings) {
diff --git a/src/DotNetOpenAuth/OpenId/Messages/AssociateSuccessfulResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/AssociateSuccessfulResponse.cs
index e3d280f..db4937e 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/AssociateSuccessfulResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/AssociateSuccessfulResponse.cs
@@ -99,8 +99,11 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// Called to create the Association based on a request previously given by the Relying Party.
/// </summary>
/// <param name="request">The prior request for an association.</param>
+ /// <param name="associationStore">The Provider's association store.</param>
/// <param name="securitySettings">The security settings for the Provider. Should be <c>null</c> for Relying Parties.</param>
- /// <returns>The created association.</returns>
+ /// <returns>
+ /// The created association.
+ /// </returns>
/// <remarks>
/// The response message is updated to include the details of the created association by this method.
/// This method is called by both the Provider and the Relying Party, but actually performs
@@ -132,13 +135,16 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// Called to create the Association based on a request previously given by the Relying Party.
/// </summary>
/// <param name="request">The prior request for an association.</param>
+ /// <param name="associationStore">The Provider's association store.</param>
/// <param name="securitySettings">The security settings of the Provider.</param>
- /// <returns>The created association.</returns>
+ /// <returns>
+ /// The created association.
+ /// </returns>
/// <remarks>
- /// <para>The caller will update this message's <see cref="ExpiresIn"/> and <see cref="AssociationHandle"/>
+ /// <para>The caller will update this message's <see cref="ExpiresIn"/> and <see cref="AssociationHandle"/>
/// properties based on the <see cref="Association"/> returned by this method, but any other
/// association type specific properties must be set by this method.</para>
- /// <para>The response message is updated to include the details of the created association by this method,
+ /// <para>The response message is updated to include the details of the created association by this method,
/// but the resulting association is <i>not</i> added to the association store and must be done by the caller.</para>
/// </remarks>
protected abstract Association CreateAssociationAtProvider(AssociateRequest request, ProviderAssociationStore associationStore, ProviderSecuritySettings securitySettings);
diff --git a/src/DotNetOpenAuth/OpenId/Messages/AssociateUnencryptedResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/AssociateUnencryptedResponse.cs
index 77079cc..3647404 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/AssociateUnencryptedResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/AssociateUnencryptedResponse.cs
@@ -37,15 +37,18 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// Called to create the Association based on a request previously given by the Relying Party.
/// </summary>
/// <param name="request">The prior request for an association.</param>
+ /// <param name="associationStore">The Provider's association store.</param>
/// <param name="securitySettings">The security settings of the Provider.</param>
- /// <returns>The created association.</returns>
+ /// <returns>
+ /// The created association.
+ /// </returns>
/// <remarks>
- /// <para>The caller will update this message's
- /// <see cref="AssociateSuccessfulResponse.ExpiresIn"/> and
- /// <see cref="AssociateSuccessfulResponse.AssociationHandle"/>
+ /// <para>The caller will update this message's
+ /// <see cref="AssociateSuccessfulResponse.ExpiresIn"/> and
+ /// <see cref="AssociateSuccessfulResponse.AssociationHandle"/>
/// properties based on the <see cref="Association"/> returned by this method, but any other
/// association type specific properties must be set by this method.</para>
- /// <para>The response message is updated to include the details of the created association by this method,
+ /// <para>The response message is updated to include the details of the created association by this method,
/// but the resulting association is <i>not</i> added to the association store and must be done by the caller.</para>
/// </remarks>
protected override Association CreateAssociationAtProvider(AssociateRequest request, ProviderAssociationStore associationStore, ProviderSecuritySettings securitySettings) {
diff --git a/src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationResponse.cs
index e4e8c7c..5d10ca4 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationResponse.cs
@@ -47,7 +47,7 @@ namespace DotNetOpenAuth.OpenId.Messages {
// is not valid (any longer). OpenID 2.0 section 11.4.2.2.
IndirectSignedResponse signedResponse = new IndirectSignedResponse(request, provider.Channel);
string invalidateHandle = ((ITamperResistantOpenIdMessage)signedResponse).InvalidateHandle;
- if (!string.IsNullOrEmpty(invalidateHandle) && provider.AssociationStore.IsValid(signedResponse, AssociationRelyingPartyType.Smart, invalidateHandle) == null) {
+ if (!string.IsNullOrEmpty(invalidateHandle) && !provider.AssociationStore.IsValid(signedResponse, AssociationRelyingPartyType.Smart, invalidateHandle)) {
this.InvalidateHandle = invalidateHandle;
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Provider/AssociationDataBag.cs b/src/DotNetOpenAuth/OpenId/Provider/AssociationDataBag.cs
index 18f7c0f..3caf05e 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/AssociationDataBag.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/AssociationDataBag.cs
@@ -12,31 +12,49 @@ namespace DotNetOpenAuth.OpenId.Provider {
using System.Text;
using DotNetOpenAuth.Messaging;
- internal class AssociationDataBag : DataBag, IStreamSerializingMessage {
+ /// <summary>
+ /// A signed and encrypted serialization of an association.
+ /// </summary>
+ internal class AssociationDataBag : DataBag, IStreamSerializingDataBag {
/// <summary>
/// Initializes a new instance of the <see cref="AssociationDataBag"/> class.
/// </summary>
public AssociationDataBag() {
}
+ /// <summary>
+ /// Gets or sets the association secret.
+ /// </summary>
[MessagePart(IsRequired = true)]
internal byte[] Secret { get; set; }
+ /// <summary>
+ /// Gets or sets the UTC time that this association expires.
+ /// </summary>
[MessagePart(IsRequired = true)]
internal DateTime ExpiresUtc { get; set; }
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is for "dumb" mode RPs.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if this instance is private association; otherwise, <c>false</c>.
+ /// </value>
[MessagePart(IsRequired = true)]
internal bool IsPrivateAssociation {
get { return this.AssociationType == AssociationRelyingPartyType.Dumb; }
set { this.AssociationType = value ? AssociationRelyingPartyType.Dumb : AssociationRelyingPartyType.Smart; }
}
+ /// <summary>
+ /// Gets or sets the type of the association (shared or private, a.k.a. smart or dumb).
+ /// </summary>
internal AssociationRelyingPartyType AssociationType { get; set; }
- internal static IDataBagFormatter<AssociationDataBag> CreateFormatter(byte[] symmetricSecret) {
- return new BinaryDataBagFormatter<AssociationDataBag>(symmetricSecret, signed: true, encrypted: true);
- }
-
+ /// <summary>
+ /// Serializes the instance to the specified stream.
+ /// </summary>
+ /// <param name="stream">The stream.</param>
public void Serialize(Stream stream) {
var writer = new BinaryWriter(stream);
writer.Write(this.IsPrivateAssociation);
@@ -45,11 +63,24 @@ namespace DotNetOpenAuth.OpenId.Provider {
writer.Flush();
}
+ /// <summary>
+ /// Initializes the fields on this instance from the specified stream.
+ /// </summary>
+ /// <param name="stream">The stream.</param>
public void Deserialize(Stream stream) {
var reader = new BinaryReader(stream);
this.IsPrivateAssociation = reader.ReadBoolean();
this.Secret = reader.ReadBuffer();
this.ExpiresUtc = TimestampEncoder.Epoch + TimeSpan.FromSeconds(reader.ReadInt32());
}
+
+ /// <summary>
+ /// Creates the formatter used for serialization of this type.
+ /// </summary>
+ /// <param name="symmetricSecret">The OpenID Provider's private symmetric secret to use to encrypt and sign the association data.</param>
+ /// <returns>A formatter for serialization.</returns>
+ internal static IDataBagFormatter<AssociationDataBag> CreateFormatter(byte[] symmetricSecret) {
+ return new BinaryDataBagFormatter<AssociationDataBag>(symmetricSecret, signed: true, encrypted: true);
+ }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
index 304edbe..d31f5f7 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
@@ -73,7 +73,6 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// <summary>
/// Initializes a new instance of the <see cref="OpenIdProvider"/> class.
/// </summary>
- /// <param name="associationStore">The association store to use. Cannot be null.</param>
/// <param name="nonceStore">The nonce store to use. Cannot be null.</param>
private OpenIdProvider(INonceStore nonceStore) {
Contract.Requires<ArgumentNullException>(nonceStore != null);
@@ -178,6 +177,9 @@ namespace DotNetOpenAuth.OpenId.Provider {
get { return this.Channel.WebRequestHandler; }
}
+ /// <summary>
+ /// Gets the association store.
+ /// </summary>
internal ProviderAssociationStore AssociationStore { get; private set; }
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/Provider/ProviderAssociationStore.cs b/src/DotNetOpenAuth/OpenId/Provider/ProviderAssociationStore.cs
index e503317..be4d01c 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/ProviderAssociationStore.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/ProviderAssociationStore.cs
@@ -5,12 +5,11 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OpenId.Provider {
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
using DotNetOpenAuth.Messaging;
+ /// <summary>
+ /// The OpenID Provider association serializer, used to encode/decode association handles.
+ /// </summary>
internal class ProviderAssociationStore {
/// <summary>
/// Initializes a new instance of the <see cref="ProviderAssociationStore"/> class.
@@ -24,23 +23,50 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// </summary>
internal byte[] Secret { get; set; }
+ /// <summary>
+ /// Encodes the specified association data bag.
+ /// </summary>
+ /// <param name="associationDataBag">The association data bag.</param>
+ /// <returns>The association handle that represents this association.</returns>
internal string Encode(AssociationDataBag associationDataBag) {
var formatter = AssociationDataBag.CreateFormatter(this.Secret);
return formatter.Serialize(associationDataBag);
}
+ /// <summary>
+ /// Retrieves an association given an association handle.
+ /// </summary>
+ /// <param name="containingMessage">The OpenID message that referenced this association handle.</param>
+ /// <param name="associationType">The expected type of the retrieved association.</param>
+ /// <param name="handle">The association handle.</param>
+ /// <returns>An association instance, or <c>null</c> if the association has expired or the signature is incorrect (which may be because the OP's symmetric key has changed).</returns>
+ /// <exception cref="ProtocolException">Thrown if the association is not of the expected type.</exception>
internal Association Decode(IProtocolMessage containingMessage, AssociationRelyingPartyType associationType, string handle) {
var formatter = AssociationDataBag.CreateFormatter(this.Secret);
- var bag = formatter.Deserialize(containingMessage, handle);
+ AssociationDataBag bag;
+ try {
+ bag = formatter.Deserialize(containingMessage, handle);
+ } catch (ProtocolException) {
+ return null;
+ }
+
ErrorUtilities.VerifyProtocol(bag.AssociationType == associationType, "Unexpected association type.");
Association assoc = Association.Deserialize(handle, bag.ExpiresUtc, bag.Secret);
- return assoc;
+ return assoc.IsExpired ? null : assoc;
}
+ /// <summary>
+ /// Determines whether the association with the specified handle is (still) valid.
+ /// </summary>
+ /// <param name="containingMessage">The OpenID message that referenced this association handle.</param>
+ /// <param name="associationType">The expected type of the retrieved association.</param>
+ /// <param name="handle">The association handle.</param>
+ /// <returns>
+ /// <c>true</c> if the specified containing message is valid; otherwise, <c>false</c>.
+ /// </returns>
internal bool IsValid(IProtocolMessage containingMessage, AssociationRelyingPartyType associationType, string handle) {
try {
- this.Decode(containingMessage, associationType, handle);
- return true;
+ return this.Decode(containingMessage, associationType, handle) != null;
} catch (ProtocolException) {
return false;
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AssociationMemoryStore.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AssociationMemoryStore.cs
index 00540b4..1dc8126 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/AssociationMemoryStore.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AssociationMemoryStore.cs
@@ -12,7 +12,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Manages a set of associations in memory only (no database).
/// </summary>
- /// <typeparam name="Uri">The type of the key.</typeparam>
/// <remarks>
/// This class should be used for low-to-medium traffic relying party sites that can afford to lose associations
/// if the app pool was ever restarted. High traffic relying parties and providers should write their own
diff --git a/src/DotNetOpenAuth/OpenId/Associations.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/Associations.cs
index cf49d1c..b171bec 100644
--- a/src/DotNetOpenAuth/OpenId/Associations.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/Associations.cs
@@ -4,7 +4,7 @@
// </copyright>
//-----------------------------------------------------------------------
-namespace DotNetOpenAuth.OpenId {
+namespace DotNetOpenAuth.OpenId.RelyingParty {
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/IAssociationStore.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/IAssociationStore.cs
index 63c6526..695aa66 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/IAssociationStore.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/IAssociationStore.cs
@@ -70,9 +70,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
- /// Code Contract for the <see cref="IAssociationStore&lt;Uri&gt;"/> class.
+ /// Code Contract for the <see cref="IAssociationStore"/> class.
/// </summary>
- /// <typeparam name="Uri">The type of the key.</typeparam>
[ContractClassFor(typeof(IAssociationStore))]
internal abstract class IAssociationStoreContract : IAssociationStore {
#region IAssociationStore Members