//----------------------------------------------------------------------- // // Copyright (c) Outercurve Foundation. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.OpenId.ChannelElements { using System; using System.Collections.Generic; using System.Linq; using System.Text; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.Messaging.Bindings; using DotNetOpenAuth.OpenId.Extensions; using DotNetOpenAuth.OpenId.RelyingParty; using Validation; /// /// The messaging channel for OpenID relying parties. /// internal class OpenIdRelyingPartyChannel : OpenIdChannel { /// /// Initializes a new instance of the class. /// /// The association store to use. /// The nonce store to use. /// The security settings to apply. /// The host factories. internal OpenIdRelyingPartyChannel(ICryptoKeyStore cryptoKeyStore, INonceStore nonceStore, RelyingPartySecuritySettings securitySettings, IHostFactories hostFactories) : this(cryptoKeyStore, nonceStore, new OpenIdRelyingPartyMessageFactory(), securitySettings, false, hostFactories) { Requires.NotNull(securitySettings, "securitySettings"); } /// /// Initializes a new instance of the class. /// /// The association store to use. /// The nonce store to use. /// An object that knows how to distinguish the various OpenID message types for deserialization purposes. /// The security settings to apply. /// A value indicating whether the channel is set up with no functional security binding elements. /// The host factories. private OpenIdRelyingPartyChannel(ICryptoKeyStore cryptoKeyStore, INonceStore nonceStore, IMessageFactory messageTypeProvider, RelyingPartySecuritySettings securitySettings, bool nonVerifying, IHostFactories hostFactories) : base(messageTypeProvider, InitializeBindingElements(cryptoKeyStore, nonceStore, securitySettings, nonVerifying), hostFactories) { Requires.NotNull(messageTypeProvider, "messageTypeProvider"); Requires.NotNull(securitySettings, "securitySettings"); Assumes.True(!nonVerifying || securitySettings is RelyingPartySecuritySettings); } /// /// A value indicating whether the channel is set up /// with no functional security binding elements. /// /// A new instance that will not perform verification on incoming messages or apply any security to outgoing messages. /// /// A value of true allows the relying party to preview incoming /// messages without invalidating nonces or checking signatures. /// Setting this to true poses a great security risk and is only /// present to support the OpenIdAjaxTextBox which needs to preview /// messages, and will validate them later. /// internal static OpenIdChannel CreateNonVerifyingChannel() { return new OpenIdRelyingPartyChannel(null, null, new OpenIdRelyingPartyMessageFactory(), new RelyingPartySecuritySettings(), true, new DefaultOpenIdHostFactories()); } /// /// Initializes the binding elements. /// /// The crypto key store. /// The nonce store to use. /// The security settings to apply. Must be an instance of either or ProviderSecuritySettings. /// A value indicating whether the channel is set up with no functional security binding elements. /// /// An array of binding elements which may be used to construct the channel. /// private static IChannelBindingElement[] InitializeBindingElements(ICryptoKeyStore cryptoKeyStore, INonceStore nonceStore, RelyingPartySecuritySettings securitySettings, bool nonVerifying) { Requires.NotNull(securitySettings, "securitySettings"); SigningBindingElement signingElement; signingElement = nonVerifying ? null : new RelyingPartySigningBindingElement(new CryptoKeyStoreAsRelyingPartyAssociationStore(cryptoKeyStore ?? new MemoryCryptoKeyStore())); var extensionFactory = OpenIdExtensionFactoryAggregator.LoadFromConfiguration(); List elements = new List(8); elements.Add(new ExtensionsBindingElementRelyingParty(extensionFactory, securitySettings)); elements.Add(new RelyingPartySecurityOptions(securitySettings)); elements.Add(new BackwardCompatibilityBindingElement()); ReturnToNonceBindingElement requestNonceElement = null; if (cryptoKeyStore != null) { if (nonceStore != null) { // There is no point in having a ReturnToNonceBindingElement without // a ReturnToSignatureBindingElement because the nonce could be // artificially changed without it. requestNonceElement = new ReturnToNonceBindingElement(nonceStore, securitySettings); elements.Add(requestNonceElement); } // It is important that the return_to signing element comes last // so that the nonce is included in the signature. elements.Add(new ReturnToSignatureBindingElement(cryptoKeyStore)); } ErrorUtilities.VerifyOperation(!securitySettings.RejectUnsolicitedAssertions || requestNonceElement != null, OpenIdStrings.UnsolicitedAssertionRejectionRequiresNonceStore); if (nonVerifying) { elements.Add(new SkipSecurityBindingElement()); } else { if (nonceStore != null) { elements.Add(new StandardReplayProtectionBindingElement(nonceStore, true)); } elements.Add(new StandardExpirationBindingElement()); elements.Add(signingElement); } return elements.ToArray(); } } }