summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OpenId/OpenId/Provider/ProviderAssociationHandleEncoder.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.OpenId/OpenId/Provider/ProviderAssociationHandleEncoder.cs')
-rw-r--r--src/DotNetOpenAuth.OpenId/OpenId/Provider/ProviderAssociationHandleEncoder.cs84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/DotNetOpenAuth.OpenId/OpenId/Provider/ProviderAssociationHandleEncoder.cs b/src/DotNetOpenAuth.OpenId/OpenId/Provider/ProviderAssociationHandleEncoder.cs
new file mode 100644
index 0000000..5de560c
--- /dev/null
+++ b/src/DotNetOpenAuth.OpenId/OpenId/Provider/ProviderAssociationHandleEncoder.cs
@@ -0,0 +1,84 @@
+//-----------------------------------------------------------------------
+// <copyright file="ProviderAssociationHandleEncoder.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.Provider {
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Threading;
+ using DotNetOpenAuth.Configuration;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.Messaging.Bindings;
+
+ /// <summary>
+ /// Provides association storage in the association handle itself, but embedding signed and encrypted association
+ /// details in the handle.
+ /// </summary>
+ public class ProviderAssociationHandleEncoder : IProviderAssociationStore {
+ /// <summary>
+ /// The name of the bucket in which to store keys that encrypt association data into association handles.
+ /// </summary>
+ internal const string AssociationHandleEncodingSecretBucket = "https://localhost/dnoa/association_handles";
+
+ /// <summary>
+ /// The crypto key store used to persist encryption keys.
+ /// </summary>
+ private readonly ICryptoKeyStore cryptoKeyStore;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ProviderAssociationHandleEncoder"/> class.
+ /// </summary>
+ /// <param name="cryptoKeyStore">The crypto key store.</param>
+ public ProviderAssociationHandleEncoder(ICryptoKeyStore cryptoKeyStore) {
+ Contract.Requires<ArgumentNullException>(cryptoKeyStore != null);
+ this.cryptoKeyStore = cryptoKeyStore;
+ }
+
+ /// <summary>
+ /// Encodes the specified association data bag.
+ /// </summary>
+ /// <param name="secret">The symmetric secret.</param>
+ /// <param name="expiresUtc">The UTC time that the association should expire.</param>
+ /// <param name="privateAssociation">A value indicating whether this is a private association.</param>
+ /// <returns>
+ /// The association handle that represents this association.
+ /// </returns>
+ public string Serialize(byte[] secret, DateTime expiresUtc, bool privateAssociation) {
+ var associationDataBag = new AssociationDataBag {
+ Secret = secret,
+ IsPrivateAssociation = privateAssociation,
+ ExpiresUtc = expiresUtc,
+ };
+
+ var formatter = AssociationDataBag.CreateFormatter(this.cryptoKeyStore, AssociationHandleEncodingSecretBucket, expiresUtc - DateTime.UtcNow);
+ 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="privateAssociation">A value indicating whether a private association is expected.</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>
+ public Association Deserialize(IProtocolMessage containingMessage, bool privateAssociation, string handle) {
+ var formatter = AssociationDataBag.CreateFormatter(this.cryptoKeyStore, AssociationHandleEncodingSecretBucket);
+ AssociationDataBag bag;
+ try {
+ bag = formatter.Deserialize(containingMessage, handle);
+ } catch (ProtocolException ex) {
+ Logger.OpenId.Error("Rejecting an association because deserialization of the encoded handle failed.", ex);
+ return null;
+ }
+
+ ErrorUtilities.VerifyProtocol(bag.IsPrivateAssociation == privateAssociation, "Unexpected association type.");
+ Association assoc = Association.Deserialize(handle, bag.ExpiresUtc, bag.Secret);
+ return assoc.IsExpired ? null : assoc;
+ }
+ }
+}