//----------------------------------------------------------------------- // // Copyright (c) Outercurve Foundation. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.OpenId.Provider { using System; using System.Threading; using DotNetOpenAuth.Configuration; using DotNetOpenAuth.Logging; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.Messaging.Bindings; using Validation; /// /// Provides association storage in the association handle itself, by embedding signed and encrypted association /// details in the handle. /// public class ProviderAssociationHandleEncoder : IProviderAssociationStore { /// /// The name of the bucket in which to store keys that encrypt association data into association handles. /// internal const string AssociationHandleEncodingSecretBucket = "https://localhost/dnoa/association_handles"; /// /// The crypto key store used to persist encryption keys. /// private readonly ICryptoKeyStore cryptoKeyStore; /// /// Initializes a new instance of the class. /// /// The crypto key store. public ProviderAssociationHandleEncoder(ICryptoKeyStore cryptoKeyStore) { Requires.NotNull(cryptoKeyStore, "cryptoKeyStore"); this.cryptoKeyStore = cryptoKeyStore; } /// /// Encodes the specified association data bag. /// /// The symmetric secret. /// The UTC time that the association should expire. /// A value indicating whether this is a private association. /// /// The association handle that represents this association. /// 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); } /// /// Retrieves an association given an association handle. /// /// The OpenID message that referenced this association handle. /// A value indicating whether a private association is expected. /// The association handle. /// /// An association instance, or null if the association has expired or the signature is incorrect (which may be because the OP's symmetric key has changed). /// /// Thrown if the association is not of the expected type. public Association Deserialize(IProtocolMessage containingMessage, bool privateAssociation, string handle) { var formatter = AssociationDataBag.CreateFormatter(this.cryptoKeyStore, AssociationHandleEncodingSecretBucket); AssociationDataBag bag = new AssociationDataBag(); try { formatter.Deserialize(bag, handle, containingMessage, Protocol.Default.openid.assoc_handle); } catch (ProtocolException ex) { Logger.OpenId.ErrorException("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; } } }