Esempio n. 1
0
		/// <summary>
		/// Initializes a new instance of the <see cref="ClientBase" /> class.
		/// </summary>
		/// <param name="authorizationServer">The token issuer.</param>
		/// <param name="clientIdentifier">The client identifier.</param>
		/// <param name="clientCredentialApplicator">The tool to use to apply client credentials to authenticated requests to the Authorization Server.
		/// May be <c>null</c> for clients with no secret or other means of authentication.</param>
		/// <param name="hostFactories">The host factories.</param>
		protected ClientBase(AuthorizationServerDescription authorizationServer, string clientIdentifier = null, ClientCredentialApplicator clientCredentialApplicator = null, IHostFactories hostFactories = null) {
			Requires.NotNull(authorizationServer, "authorizationServer");
			this.AuthorizationServer = authorizationServer;
			this.Channel = new OAuth2ClientChannel(hostFactories);
			this.ClientIdentifier = clientIdentifier;
			this.ClientCredentialApplicator = clientCredentialApplicator;
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="StandardMessageFactoryChannel" /> class.
		/// </summary>
		/// <param name="messageTypes">The message types that might be encountered.</param>
		/// <param name="versions">All the possible message versions that might be encountered.</param>
		/// <param name="hostFactories">The host factories.</param>
		/// <param name="bindingElements">The binding elements to use in sending and receiving messages.
		/// The order they are provided is used for outgoing messgaes, and reversed for incoming messages.</param>
		protected StandardMessageFactoryChannel(ICollection<Type> messageTypes, ICollection<Version> versions, IHostFactories hostFactories, IChannelBindingElement[] bindingElements = null)
			: base(new StandardMessageFactory(), bindingElements ?? new IChannelBindingElement[0], hostFactories) {
			Requires.NotNull(messageTypes, "messageTypes");
			Requires.NotNull(versions, "versions");

			this.messageTypes = messageTypes;
			this.versions = versions;
			this.StandardMessageFactory.AddMessageTypes(GetMessageDescriptions(this.messageTypes, this.versions, this.MessageDescriptions));
		}
Esempio n. 3
0
		/// <summary>
		/// Gets the URL of the RP icon for the OP to display.
		/// </summary>
		/// <param name="realm">The realm of the RP where the authentication request originated.</param>
		/// <param name="hostFactories">The host factories.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <returns>
		/// A sequence of the RP's icons it has available for the Provider to display, in decreasing preferred order.
		/// </returns>
		/// <value>The icon URL.</value>
		/// <remarks>
		/// This property is automatically set for the OP with the result of RP discovery.
		/// RPs should set this value by including an entry such as this in their XRDS document.
		/// <example>
		/// &lt;Service xmlns="xri://$xrd*($v*2.0)"&gt;
		/// &lt;Type&gt;http://specs.openid.net/extensions/ui/icon&lt;/Type&gt;
		/// &lt;URI&gt;http://consumer.example.com/images/image.jpg&lt;/URI&gt;
		/// &lt;/Service&gt;
		/// </example>
		/// </remarks>
		public static async Task<IEnumerable<Uri>> GetRelyingPartyIconUrlsAsync(Realm realm, IHostFactories hostFactories, CancellationToken cancellationToken) {
			Requires.NotNull(realm, "realm");
			Requires.NotNull(hostFactories, "hostFactories");

			XrdsDocument xrds = await realm.DiscoverAsync(hostFactories, false, cancellationToken);
			if (xrds == null) {
				return Enumerable.Empty<Uri>();
			} else {
				return xrds.FindRelyingPartyIcons();
			}
		}
Esempio n. 4
0
		protected OAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, ITokenManager tokenManager, SecuritySettings securitySettings, IMessageFactory messageTypeProvider, IChannelBindingElement[] bindingElements, IHostFactories hostFactories = null)
			: base(messageTypeProvider, bindingElements, hostFactories ?? new DefaultOAuthHostFactories()) {
			Requires.NotNull(tokenManager, "tokenManager");
			Requires.NotNull(securitySettings, "securitySettings");
			Requires.NotNull(signingBindingElement, "signingBindingElement");
			Requires.That(signingBindingElement.SignatureCallback == null, "signingBindingElement", OAuthStrings.SigningElementAlreadyAssociatedWithChannel);
			Requires.NotNull(bindingElements, "bindingElements");

			this.TokenManager = tokenManager;
			signingBindingElement.SignatureCallback = this.SignatureCallback;
		}
		internal OAuthServiceProviderChannel(ITamperProtectionChannelBindingElement signingBindingElement, INonceStore store, IServiceProviderTokenManager tokenManager, ServiceProviderSecuritySettings securitySettings, IMessageFactory messageTypeProvider = null, IHostFactories hostFactories = null)
			: base(
			signingBindingElement,
			tokenManager,
			securitySettings,
			messageTypeProvider ?? new OAuthServiceProviderMessageFactory(tokenManager),
			InitializeBindingElements(signingBindingElement, store, tokenManager, securitySettings),
			hostFactories) {
			Requires.NotNull(tokenManager, "tokenManager");
			Requires.NotNull(securitySettings, "securitySettings");
			Requires.NotNull(signingBindingElement, "signingBindingElement");
		}
Esempio n. 6
0
		/// <summary>
		/// Initializes a new instance of the <see cref="Consumer" /> class.
		/// </summary>
		/// <param name="consumerKey">The consumer key.</param>
		/// <param name="consumerSecret">The consumer secret.</param>
		/// <param name="serviceProvider">The service provider.</param>
		/// <param name="temporaryCredentialStorage">The temporary credential storage.</param>
		/// <param name="hostFactories">The host factories.</param>
		public Consumer(
			string consumerKey,
			string consumerSecret,
			ServiceProviderDescription serviceProvider,
			ITemporaryCredentialStorage temporaryCredentialStorage,
			IHostFactories hostFactories = null) {
			this.ConsumerKey = consumerKey;
			this.ConsumerSecret = consumerSecret;
			this.ServiceProvider = serviceProvider;
			this.TemporaryCredentialStorage = temporaryCredentialStorage;
			this.HostFactories = hostFactories ?? new DefaultOAuthHostFactories();
		}
Esempio n. 7
0
		/// <summary>
		/// Initializes a new instance of the <see cref="OpenIdProvider" /> class.
		/// </summary>
		/// <param name="nonceStore">The nonce store to use.  Cannot be null.</param>
		/// <param name="cryptoKeyStore">The crypto key store.  Cannot be null.</param>
		/// <param name="hostFactories">The host factories.</param>
		private OpenIdProvider(INonceStore nonceStore, ICryptoKeyStore cryptoKeyStore, IHostFactories hostFactories) {
			Requires.NotNull(nonceStore, "nonceStore");
			Requires.NotNull(cryptoKeyStore, "cryptoKeyStore");

			this.SecuritySettings = OpenIdElement.Configuration.Provider.SecuritySettings.CreateSecuritySettings();
			this.behaviors.CollectionChanged += this.OnBehaviorsChanged;
			foreach (var behavior in OpenIdElement.Configuration.Provider.Behaviors.CreateInstances(false, null)) {
				this.behaviors.Add(behavior);
			}

			this.AssociationStore = new SwitchingAssociationStore(cryptoKeyStore, this.SecuritySettings);
			this.Channel = new OpenIdProviderChannel(this.AssociationStore, nonceStore, this.SecuritySettings, hostFactories);
			this.CryptoKeyStore = cryptoKeyStore;
			this.discoveryServices = new IdentifierDiscoveryServices(this);

			Reporting.RecordFeatureAndDependencyUse(this, nonceStore);
		}
Esempio n. 8
0
		/// <summary>
		/// Initializes a new instance of the <see cref="OpenIdChannel" /> class.
		/// </summary>
		/// <param name="messageTypeProvider">A class prepared to analyze incoming messages and indicate what concrete
		/// message types can deserialize from it.</param>
		/// <param name="bindingElements">The binding elements to use in sending and receiving messages.</param>
		/// <param name="hostFactories">The host factories.</param>
		protected OpenIdChannel(IMessageFactory messageTypeProvider, IChannelBindingElement[] bindingElements, IHostFactories hostFactories)
			: base(messageTypeProvider, bindingElements, hostFactories ?? new DefaultOpenIdHostFactories()) {
			Requires.NotNull(messageTypeProvider, "messageTypeProvider");

			// Customize the binding element order, since we play some tricks for higher
			// security and backward compatibility with older OpenID versions.
			var outgoingBindingElements = new List<IChannelBindingElement>(bindingElements);
			var incomingBindingElements = new List<IChannelBindingElement>(bindingElements);
			incomingBindingElements.Reverse();

			// Customize the order of the incoming elements by moving the return_to elements in front.
			var backwardCompatibility = incomingBindingElements.OfType<BackwardCompatibilityBindingElement>().SingleOrDefault();
			var returnToSign = incomingBindingElements.OfType<ReturnToSignatureBindingElement>().SingleOrDefault();
			if (backwardCompatibility != null) {
				incomingBindingElements.MoveTo(0, backwardCompatibility);
			}
			if (returnToSign != null) {
				// Yes, this is intentionally, shifting the backward compatibility
				// binding element to second position.
				incomingBindingElements.MoveTo(0, returnToSign);
			}

			this.CustomizeBindingElementOrder(outgoingBindingElements, incomingBindingElements);
		}
 /// <summary>
 /// Initializes a new instance of the <see cref="OpenIdRelyingParty" /> class.
 /// </summary>
 /// <param name="applicationStore">The application store.  If <c>null</c>, the relying party will always operate in "stateless/dumb mode".</param>
 /// <param name="hostFactories">The host factories.</param>
 public OpenIdRelyingParty(ICryptoKeyAndNonceStore applicationStore, IHostFactories hostFactories = null)
     : this(applicationStore, applicationStore, hostFactories)
 {
 }
Esempio n. 10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ClientBase" /> class.
 /// </summary>
 /// <param name="authorizationServer">The token issuer.</param>
 /// <param name="clientIdentifier">The client identifier.</param>
 /// <param name="clientCredentialApplicator">The tool to use to apply client credentials to authenticated requests to the Authorization Server.
 /// May be <c>null</c> for clients with no secret or other means of authentication.</param>
 /// <param name="hostFactories">The host factories.</param>
 protected ClientBase(AuthorizationServerDescription authorizationServer, string clientIdentifier = null, ClientCredentialApplicator clientCredentialApplicator = null, IHostFactories hostFactories = null)
 {
     Requires.NotNull(authorizationServer, "authorizationServer");
     this.AuthorizationServer        = authorizationServer;
     this.Channel                    = new OAuth2ClientChannel(hostFactories);
     this.ClientIdentifier           = clientIdentifier;
     this.ClientCredentialApplicator = clientCredentialApplicator;
 }
Esempio n. 11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OAuth2ClientChannel" /> class.
 /// </summary>
 /// <param name="hostFactories">The host factories.</param>
 internal OAuth2ClientChannel(IHostFactories hostFactories)
     : base(MessageTypes, hostFactories: hostFactories)
 {
 }
Esempio n. 12
0
		/// <summary>
		/// Initializes a new instance of the <see cref="UserAgentClient"/> class.
		/// </summary>
		/// <param name="authorizationEndpoint">The authorization endpoint.</param>
		/// <param name="tokenEndpoint">The token endpoint.</param>
		/// <param name="clientIdentifier">The client identifier.</param>
		/// <param name="clientSecret">The client secret.</param>
		public UserAgentClient(Uri authorizationEndpoint, Uri tokenEndpoint, string clientIdentifier = null, string clientSecret = null, IHostFactories hostFactories = null)
			: this(authorizationEndpoint, tokenEndpoint, clientIdentifier, DefaultSecretApplicator(clientSecret), hostFactories) {
		}
 /// <summary>
 /// Initializes a new instance of the <see cref="WebServerClient" /> class.
 /// </summary>
 /// <param name="authorizationServer">The authorization server.</param>
 /// <param name="clientIdentifier">The client identifier.</param>
 /// <param name="clientSecret">The client secret.</param>
 /// <param name="hostFactories">The host factories.</param>
 public WebServerClient(AuthorizationServerDescription authorizationServer, string clientIdentifier = null, string clientSecret = null, IHostFactories hostFactories = null)
     : this(authorizationServer, clientIdentifier, DefaultSecretApplicator(clientSecret), hostFactories)
 {
 }
		/// <summary>
		/// Initializes a new instance of the <see cref="OpenIdProviderChannel" /> class.
		/// </summary>
		/// <param name="cryptoKeyStore">The association store to use.</param>
		/// <param name="nonceStore">The nonce store to use.</param>
		/// <param name="messageTypeProvider">An object that knows how to distinguish the various OpenID message types for deserialization purposes.</param>
		/// <param name="securitySettings">The security settings.</param>
		/// <param name="hostFactories">The host factories.</param>
		private OpenIdProviderChannel(IProviderAssociationStore cryptoKeyStore, INonceStore nonceStore, IMessageFactory messageTypeProvider, ProviderSecuritySettings securitySettings, IHostFactories hostFactories)
			: base(messageTypeProvider, InitializeBindingElements(cryptoKeyStore, nonceStore, securitySettings), hostFactories) {
			Requires.NotNull(cryptoKeyStore, "cryptoKeyStore");
			Requires.NotNull(messageTypeProvider, "messageTypeProvider");
			Requires.NotNull(securitySettings, "securitySettings");
		}
Esempio n. 15
0
 internal TestChannel(MessageDescriptionCollection messageDescriptions, IHostFactories hostFactories = null)
     : this(hostFactories) {
     this.MessageDescriptions = messageDescriptions;
 }
Esempio n. 16
0
 public OAuth2ChannelBase(Type[] messageTypes, IChannelBindingElement[] channelBindingElements = null, IHostFactories hostFactories = null)
     : base(messageTypes, Versions, hostFactories ?? new DefaultOAuthHostFactories(), channelBindingElements ?? new IChannelBindingElement[0])
 {
 }
Esempio n. 17
0
		/// <summary>
		/// Searches for an XRDS document at the realm URL, and if found, searches
		/// for a description of a relying party endpoints (OpenId login pages).
		/// </summary>
		/// <param name="hostFactories">The host factories.</param>
		/// <param name="allowRedirects">Whether redirects may be followed when discovering the Realm.
		/// This may be true when creating an unsolicited assertion, but must be
		/// false when performing return URL verification per 2.0 spec section 9.2.1.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <returns>
		/// The details of the endpoints if found, otherwise null.
		/// </returns>
		internal override Task<IEnumerable<RelyingPartyEndpointDescription>> DiscoverReturnToEndpointsAsync(IHostFactories hostFactories, bool allowRedirects, CancellationToken cancellationToken) {
			return Task.FromResult<IEnumerable<RelyingPartyEndpointDescription>>(this.relyingPartyDescriptions);
		}
        /// <summary>
        /// Initializes a new instance of the <see cref="StandardMessageFactoryChannel" /> class.
        /// </summary>
        /// <param name="messageTypes">The message types that might be encountered.</param>
        /// <param name="versions">All the possible message versions that might be encountered.</param>
        /// <param name="hostFactories">The host factories.</param>
        /// <param name="bindingElements">The binding elements to use in sending and receiving messages.
        /// The order they are provided is used for outgoing messgaes, and reversed for incoming messages.</param>
        protected StandardMessageFactoryChannel(ICollection <Type> messageTypes, ICollection <Version> versions, IHostFactories hostFactories, IChannelBindingElement[] bindingElements = null)
            : base(new StandardMessageFactory(), bindingElements ?? new IChannelBindingElement[0], hostFactories)
        {
            Requires.NotNull(messageTypes, "messageTypes");
            Requires.NotNull(versions, "versions");

            this.messageTypes = messageTypes;
            this.versions     = versions;
            this.StandardMessageFactory.AddMessageTypes(GetMessageDescriptions(this.messageTypes, this.versions, this.MessageDescriptions));
        }
Esempio n. 19
0
		/// <summary>
		/// Initializes a new instance of the <see cref="OpenIdProvider" /> class.
		/// </summary>
		/// <param name="applicationStore">The application store to use.  Cannot be null.</param>
		/// <param name="hostFactories">The host factories.</param>
		public OpenIdProvider(IOpenIdApplicationStore applicationStore, IHostFactories hostFactories = null)
			: this((INonceStore)applicationStore, (ICryptoKeyStore)applicationStore, hostFactories) {
			Requires.NotNull(applicationStore, "applicationStore");
		}
Esempio n. 20
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OpenIdRelyingPartyChannel" /> class.
 /// </summary>
 /// <param name="cryptoKeyStore">The association store to use.</param>
 /// <param name="nonceStore">The nonce store to use.</param>
 /// <param name="messageTypeProvider">An object that knows how to distinguish the various OpenID message types for deserialization purposes.</param>
 /// <param name="securitySettings">The security settings to apply.</param>
 /// <param name="nonVerifying">A value indicating whether the channel is set up with no functional security binding elements.</param>
 /// <param name="hostFactories">The host factories.</param>
 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);
 }
Esempio n. 21
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OpenIdRelyingPartyChannel" /> class.
 /// </summary>
 /// <param name="cryptoKeyStore">The association store to use.</param>
 /// <param name="nonceStore">The nonce store to use.</param>
 /// <param name="securitySettings">The security settings to apply.</param>
 /// <param name="hostFactories">The host factories.</param>
 internal OpenIdRelyingPartyChannel(ICryptoKeyStore cryptoKeyStore, INonceStore nonceStore, RelyingPartySecuritySettings securitySettings, IHostFactories hostFactories)
     : this(cryptoKeyStore, nonceStore, new OpenIdRelyingPartyMessageFactory(), securitySettings, false, hostFactories)
 {
     Requires.NotNull(securitySettings, "securitySettings");
 }
Esempio n. 22
0
 internal TestChannel(IMessageFactory messageTypeProvider, IChannelBindingElement[] bindingElements, IHostFactories hostFactories)
     : base(messageTypeProvider, bindingElements, hostFactories)
 {
 }
Esempio n. 23
0
        /// <summary>
        /// Searches for an XRDS document at the realm URL, and if found, searches
        /// for a description of a relying party endpoints (OpenId login pages).
        /// </summary>
        /// <param name="hostFactories">The host factories.</param>
        /// <param name="allowRedirects">Whether redirects may be followed when discovering the Realm.
        /// This may be true when creating an unsolicited assertion, but must be
        /// false when performing return URL verification per 2.0 spec section 9.2.1.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// The details of the endpoints if found; or <c>null</c> if no service document was discovered.
        /// </returns>
        internal virtual async Task <IEnumerable <RelyingPartyEndpointDescription> > DiscoverReturnToEndpointsAsync(IHostFactories hostFactories, bool allowRedirects, CancellationToken cancellationToken)
        {
            XrdsDocument xrds = await this.DiscoverAsync(hostFactories, allowRedirects, cancellationToken);

            if (xrds != null)
            {
                return(xrds.FindRelyingPartyReceivingEndpoints());
            }

            return(null);
        }
		/// <summary>
		/// Initializes a new instance of the <see cref="OAuth2ResourceServerChannel" /> class.
		/// </summary>
		/// <param name="hostFactories">The host factories.</param>
		protected internal OAuth2ResourceServerChannel(IHostFactories hostFactories = null)
			: base(MessageTypes, Versions, hostFactories ?? new OAuth.DefaultOAuthHostFactories()) {
			// TODO: add signing (authenticated request) binding element.
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="OpenIdRelyingPartyChannel" /> class.
		/// </summary>
		/// <param name="cryptoKeyStore">The association store to use.</param>
		/// <param name="nonceStore">The nonce store to use.</param>
		/// <param name="messageTypeProvider">An object that knows how to distinguish the various OpenID message types for deserialization purposes.</param>
		/// <param name="securitySettings">The security settings to apply.</param>
		/// <param name="nonVerifying">A value indicating whether the channel is set up with no functional security binding elements.</param>
		/// <param name="hostFactories">The host factories.</param>
		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);
		}
Esempio n. 26
0
 /// <summary>
 /// Creates an instance of the type described in the .config file.
 /// </summary>
 /// <param name="defaultValue">The value to return if no type is given in the .config file.</param>
 /// <param name="hostFactories">The host factories.</param>
 /// <returns>
 /// The newly instantiated type.
 /// </returns>
 public T CreateInstance(T defaultValue, IHostFactories hostFactories)
 {
     return(this.CreateInstance(defaultValue, false, hostFactories));
 }
Esempio n. 27
0
 public AzureADClient(AuthorizationServerDescription authorizationServer, string clientIdentifier = null, string clientSecret = null, IHostFactories hostFactories = null)
     : base(authorizationServer, clientIdentifier, clientSecret, hostFactories)
 {
 }
Esempio n. 28
0
		/// <summary>
		/// Initializes a new instance of the <see cref="TestBadChannel" /> class.
		/// </summary>
		/// <param name="messageFactory">The message factory. Could be <see cref="TestMessageFactory"/></param>
		/// <param name="bindingElements">The binding elements.</param>
		/// <param name="hostFactories">The host factories.</param>
		internal TestBadChannel(IMessageFactory messageFactory, IChannelBindingElement[] bindingElements, IHostFactories hostFactories)
			: base(messageFactory, bindingElements, hostFactories) {
		}
Esempio n. 29
0
        /// <summary>
        /// Gets a value indicating whether verification of the return URL claimed by the Relying Party
        /// succeeded.
        /// </summary>
        /// <param name="hostFactories">The host factories.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// Result of realm discovery.
        /// </returns>
        private async Task <RelyingPartyDiscoveryResult> IsReturnUrlDiscoverableCoreAsync(IHostFactories hostFactories, CancellationToken cancellationToken)
        {
            Requires.NotNull(hostFactories, "hostFactories");
            ErrorUtilities.VerifyInternal(this.Realm != null, "Realm should have been read or derived by now.");

            try {
                if (this.SecuritySettings.RequireSsl && this.Realm.Scheme != Uri.UriSchemeHttps)
                {
                    Logger.OpenId.WarnFormat("RP discovery failed because RequireSsl is true and RP discovery would begin at insecure URL {0}.", this.Realm);
                    return(RelyingPartyDiscoveryResult.NoServiceDocument);
                }

                var returnToEndpoints = await this.Realm.DiscoverReturnToEndpointsAsync(hostFactories, false, cancellationToken);

                if (returnToEndpoints == null)
                {
                    return(RelyingPartyDiscoveryResult.NoServiceDocument);
                }

                foreach (var returnUrl in returnToEndpoints)
                {
                    Realm discoveredReturnToUrl = returnUrl.ReturnToEndpoint;

                    // The spec requires that the return_to URLs given in an RPs XRDS doc
                    // do not contain wildcards.
                    if (discoveredReturnToUrl.DomainWildcard)
                    {
                        Logger.Yadis.WarnFormat("Realm {0} contained return_to URL {1} which contains a wildcard, which is not allowed.", Realm, discoveredReturnToUrl);
                        continue;
                    }

                    // Use the same rules as return_to/realm matching to check whether this
                    // URL fits the return_to URL we were given.
                    if (discoveredReturnToUrl.Contains(this.RequestMessage.ReturnTo))
                    {
                        // no need to keep looking after we find a match
                        return(RelyingPartyDiscoveryResult.Success);
                    }
                }
            } catch (ProtocolException ex) {
                // Don't do anything else.  We quietly fail at return_to verification and return false.
                Logger.Yadis.InfoFormat("Relying party discovery at URL {0} failed.  {1}", Realm, ex);
                return(RelyingPartyDiscoveryResult.NoServiceDocument);
            } catch (WebException ex) {
                // Don't do anything else.  We quietly fail at return_to verification and return false.
                Logger.Yadis.InfoFormat("Relying party discovery at URL {0} failed.  {1}", Realm, ex);
                return(RelyingPartyDiscoveryResult.NoServiceDocument);
            }

            return(RelyingPartyDiscoveryResult.NoMatchingReturnTo);
        }
Esempio n. 30
0
 /// <summary>
 /// Creates instances of all the types listed in the collection.
 /// </summary>
 /// <param name="allowInternals">if set to <c>true</c> then internal types may be instantiated.</param>
 /// <param name="hostFactories">The host factories.</param>
 /// <returns>
 /// A sequence of instances generated from types in this collection.  May be empty, but never null.
 /// </returns>
 internal IEnumerable <T> CreateInstances(bool allowInternals, IHostFactories hostFactories)
 {
     return(from element in this.Cast <TypeConfigurationElement <T> >()
            where !element.IsEmpty
            select element.CreateInstance(default(T), allowInternals, hostFactories));
 }
Esempio n. 31
0
		/// <summary>
		/// Initializes a new instance of the <see cref="UserAgentClient"/> class.
		/// </summary>
		/// <param name="authorizationEndpoint">The authorization endpoint.</param>
		/// <param name="tokenEndpoint">The token endpoint.</param>
		/// <param name="clientIdentifier">The client identifier.</param>
		/// <param name="clientCredentialApplicator">
		/// The tool to use to apply client credentials to authenticated requests to the Authorization Server.  
		/// May be <c>null</c> for clients with no secret or other means of authentication.
		/// </param>
		public UserAgentClient(Uri authorizationEndpoint, Uri tokenEndpoint, string clientIdentifier, ClientCredentialApplicator clientCredentialApplicator, IHostFactories hostFactories = null)
			: this(new AuthorizationServerDescription { AuthorizationEndpoint = authorizationEndpoint, TokenEndpoint = tokenEndpoint }, clientIdentifier, clientCredentialApplicator, hostFactories) {
			Requires.NotNull(authorizationEndpoint, "authorizationEndpoint");
			Requires.NotNull(tokenEndpoint, "tokenEndpoint");
		}
Esempio n. 32
0
        /// <summary>
        /// Downloads the XRDS document for this XRI.
        /// </summary>
        /// <param name="identifier">The identifier.</param>
        /// <param name="hostFactories">The host factories.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// The XRDS document.
        /// </returns>
        private static async Task <XrdsDocument> DownloadXrdsAsync(XriIdentifier identifier, IHostFactories hostFactories, CancellationToken cancellationToken)
        {
            Requires.NotNull(identifier, "identifier");
            Requires.NotNull(hostFactories, "hostFactories");

            XrdsDocument doc;

            using (var xrdsResponse = await Yadis.RequestAsync(GetXrdsUrl(identifier), identifier.IsDiscoverySecureEndToEnd, hostFactories, cancellationToken)) {
                xrdsResponse.EnsureSuccessStatusCode();
                var readerSettings = MessagingUtilities.CreateUntrustedXmlReaderSettings();
                ErrorUtilities.VerifyProtocol(xrdsResponse.Content != null, "XRDS request \"{0}\" returned no response.", GetXrdsUrl(identifier));
                await xrdsResponse.Content.LoadIntoBufferAsync();

                using (var xrdsStream = await xrdsResponse.Content.ReadAsStreamAsync()) {
                    doc = new XrdsDocument(XmlReader.Create(xrdsStream, readerSettings));
                }
            }

            ErrorUtilities.VerifyProtocol(doc.IsXrdResolutionSuccessful, OpenIdStrings.XriResolutionFailed);
            return(doc);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="WebServerClient" /> class.
 /// </summary>
 /// <param name="authorizationServer">The authorization server.</param>
 /// <param name="clientIdentifier">The client identifier.</param>
 /// <param name="clientCredentialApplicator">The tool to use to apply client credentials to authenticated requests to the Authorization Server.
 /// May be <c>null</c> for clients with no secret or other means of authentication.</param>
 /// <param name="hostFactories">The host factories.</param>
 public WebServerClient(AuthorizationServerDescription authorizationServer, string clientIdentifier, ClientCredentialApplicator clientCredentialApplicator, IHostFactories hostFactories = null)
     : base(authorizationServer, clientIdentifier, clientCredentialApplicator, hostFactories)
 {
 }
Esempio n. 34
0
		/// <summary>
		/// Initializes a new instance of the <see cref="OAuth2ClientChannel" /> class.
		/// </summary>
		/// <param name="hostFactories">The host factories.</param>
		internal OAuth2ClientChannel(IHostFactories hostFactories)
			: base(MessageTypes, hostFactories: hostFactories) {
		}
Esempio n. 35
0
        /// <summary>
        /// Constructor when using the GetAssertionAccessTokenAsync() method.
        /// </summary>
        /// <param name="authorizationServer"></param>
        /// <param name="assertionProvider">This will be queried for the assertion data.</param>
        /// <param name="hostFactories"></param>
        protected ClientBase(AuthorizationServerDescription authorizationServer, IAssertionProvider assertionProvider, IHostFactories hostFactories = null)
        {
            Requires.NotNull(authorizationServer, "authorizationServer");
            this.AuthorizationServer = authorizationServer;
            this.Channel             = new OAuth2ClientChannel(hostFactories);

            // YTML: A bit hacky, but instead of creating a new property, we can just wrap the assertionProvider as a credential applicator.
            this.ClientCredentialApplicator = new ClientCredentialApplicator.AssertionProviderApplicator(assertionProvider);
        }
        protected OAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, ITokenManager tokenManager, SecuritySettings securitySettings, IMessageFactory messageTypeProvider, IChannelBindingElement[] bindingElements, IHostFactories hostFactories = null)
            : base(messageTypeProvider, bindingElements, hostFactories ?? new DefaultOAuthHostFactories())
        {
            Requires.NotNull(tokenManager, "tokenManager");
            Requires.NotNull(securitySettings, "securitySettings");
            Requires.NotNull(signingBindingElement, "signingBindingElement");
            Requires.That(signingBindingElement.SignatureCallback == null, "signingBindingElement", OAuthStrings.SigningElementAlreadyAssociatedWithChannel);
            Requires.NotNull(bindingElements, "bindingElements");

            this.TokenManager = tokenManager;
            signingBindingElement.SignatureCallback = this.SignatureCallback;
        }
		/// <summary>
		/// Downloads the XRDS document for this XRI.
		/// </summary>
		/// <param name="identifier">The identifier.</param>
		/// <param name="hostFactories">The host factories.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <returns>
		/// The XRDS document.
		/// </returns>
		private static async Task<XrdsDocument> DownloadXrdsAsync(XriIdentifier identifier, IHostFactories hostFactories, CancellationToken cancellationToken) {
			Requires.NotNull(identifier, "identifier");
			Requires.NotNull(hostFactories, "hostFactories");

			XrdsDocument doc;
			using (var xrdsResponse = await Yadis.RequestAsync(GetXrdsUrl(identifier), identifier.IsDiscoverySecureEndToEnd, hostFactories, cancellationToken)) {
				xrdsResponse.EnsureSuccessStatusCode();
				var readerSettings = MessagingUtilities.CreateUntrustedXmlReaderSettings();
				ErrorUtilities.VerifyProtocol(xrdsResponse.Content != null, "XRDS request \"{0}\" returned no response.", GetXrdsUrl(identifier));
				await xrdsResponse.Content.LoadIntoBufferAsync();
				using (var xrdsStream = await xrdsResponse.Content.ReadAsStreamAsync()) {
					doc = new XrdsDocument(XmlReader.Create(xrdsStream, readerSettings));
				}
			}

			ErrorUtilities.VerifyProtocol(doc.IsXrdResolutionSuccessful, OpenIdStrings.XriResolutionFailed);
			return doc;
		}
 /// <summary>
 /// Initializes a new instance of the <see cref="OAuth2ResourceServerChannel" /> class.
 /// </summary>
 /// <param name="hostFactories">The host factories.</param>
 protected internal OAuth2ResourceServerChannel(IHostFactories hostFactories = null)
     : base(MessageTypes, Versions, hostFactories ?? new OAuth.DefaultOAuthHostFactories())
 {
     // TODO: add signing (authenticated request) binding element.
 }
        private OpenIdRelyingParty(ICryptoKeyStore cryptoKeyStore, INonceStore nonceStore, IHostFactories hostFactories)
        {
            // If we are a smart-mode RP (supporting associations), then we MUST also be
            // capable of storing nonces to prevent replay attacks.
            // If we're a dumb-mode RP, then 2.0 OPs are responsible for preventing replays.
            Requires.That(cryptoKeyStore == null || nonceStore != null, null, OpenIdStrings.AssociationStoreRequiresNonceStore);

            this.securitySettings = OpenIdElement.Configuration.RelyingParty.SecuritySettings.CreateSecuritySettings();

            this.behaviors.CollectionChanged += this.OnBehaviorsChanged;
            foreach (var behavior in OpenIdElement.Configuration.RelyingParty.Behaviors.CreateInstances(false, null))
            {
                this.behaviors.Add(behavior);
            }

            // Without a nonce store, we must rely on the Provider to protect against
            // replay attacks.  But only 2.0+ Providers can be expected to provide
            // replay protection.
            if (nonceStore == null &&
                this.SecuritySettings.ProtectDownlevelReplayAttacks &&
                this.SecuritySettings.MinimumRequiredOpenIdVersion < ProtocolVersion.V20)
            {
                Logger.OpenId.Warn("Raising minimum OpenID version requirement for Providers to 2.0 to protect this stateless RP from replay attacks.");
                this.SecuritySettings.MinimumRequiredOpenIdVersion = ProtocolVersion.V20;
            }

            this.channel = new OpenIdRelyingPartyChannel(cryptoKeyStore, nonceStore, this.SecuritySettings, hostFactories);
            var associationStore = cryptoKeyStore != null ? new CryptoKeyStoreAsRelyingPartyAssociationStore(cryptoKeyStore) : null;

            this.AssociationManager = new AssociationManager(this.Channel, associationStore, this.SecuritySettings);
            this.discoveryServices  = new IdentifierDiscoveryServices(this);

            Reporting.RecordFeatureAndDependencyUse(this, cryptoKeyStore, nonceStore);
        }
			public ForwardingMessageHandler(Dictionary<Uri, Func<HttpRequestMessage, Task<HttpResponseMessage>>> handlers, IHostFactories hostFactories) {
				Requires.NotNull(handlers, "handlers");

				this.handlers = handlers;
				this.hostFactories = hostFactories;
			}
		/// <summary>
		/// Initializes a new instance of the <see cref="OpenIdRelyingPartyChannel" /> class.
		/// </summary>
		/// <param name="cryptoKeyStore">The association store to use.</param>
		/// <param name="nonceStore">The nonce store to use.</param>
		/// <param name="securitySettings">The security settings to apply.</param>
		/// <param name="hostFactories">The host factories.</param>
		internal OpenIdRelyingPartyChannel(ICryptoKeyStore cryptoKeyStore, INonceStore nonceStore, RelyingPartySecuritySettings securitySettings, IHostFactories hostFactories)
			: this(cryptoKeyStore, nonceStore, new OpenIdRelyingPartyMessageFactory(), securitySettings, false, hostFactories) {
			Requires.NotNull(securitySettings, "securitySettings");
		}
Esempio n. 42
0
		/// <summary>
		/// Initializes a new instance of the <see cref="WebServerClient" /> class.
		/// </summary>
		/// <param name="authorizationServer">The authorization server.</param>
		/// <param name="clientIdentifier">The client identifier.</param>
		/// <param name="clientCredentialApplicator">The tool to use to apply client credentials to authenticated requests to the Authorization Server.
		/// May be <c>null</c> for clients with no secret or other means of authentication.</param>
		/// <param name="hostFactories">The host factories.</param>
		public WebServerClient(AuthorizationServerDescription authorizationServer, string clientIdentifier, ClientCredentialApplicator clientCredentialApplicator, IHostFactories hostFactories = null)
			: base(authorizationServer, clientIdentifier, clientCredentialApplicator, hostFactories) {
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="OpenIdProviderChannel" /> class.
		/// </summary>
		/// <param name="cryptoKeyStore">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>
		/// <param name="hostFactories">The host factories.</param>
		internal OpenIdProviderChannel(IProviderAssociationStore cryptoKeyStore, INonceStore nonceStore, ProviderSecuritySettings securitySettings, IHostFactories hostFactories)
			: this(cryptoKeyStore, nonceStore, new OpenIdProviderMessageFactory(), securitySettings, hostFactories) {
			Requires.NotNull(cryptoKeyStore, "cryptoKeyStore");
			Requires.NotNull(securitySettings, "securitySettings");
		}
Esempio n. 44
0
		internal TestChannel(IMessageFactory messageTypeProvider, IChannelBindingElement[] bindingElements, IHostFactories hostFactories)
			: base(messageTypeProvider, bindingElements, hostFactories) {
		}
Esempio n. 45
0
		internal TestChannel(IHostFactories hostFactories = null)
			: this(new TestMessageFactory(), new IChannelBindingElement[0], hostFactories ?? new DefaultOpenIdHostFactories()) {
		}
Esempio n. 46
0
        /// <summary>
        /// Gets the URL of the RP icon for the OP to display.
        /// </summary>
        /// <param name="realm">The realm of the RP where the authentication request originated.</param>
        /// <param name="hostFactories">The host factories.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// A sequence of the RP's icons it has available for the Provider to display, in decreasing preferred order.
        /// </returns>
        /// <value>The icon URL.</value>
        /// <remarks>
        /// This property is automatically set for the OP with the result of RP discovery.
        /// RPs should set this value by including an entry such as this in their XRDS document.
        /// <example>
        /// &lt;Service xmlns="xri://$xrd*($v*2.0)"&gt;
        /// &lt;Type&gt;http://specs.openid.net/extensions/ui/icon&lt;/Type&gt;
        /// &lt;URI&gt;http://consumer.example.com/images/image.jpg&lt;/URI&gt;
        /// &lt;/Service&gt;
        /// </example>
        /// </remarks>
        public static async Task <IEnumerable <Uri> > GetRelyingPartyIconUrlsAsync(Realm realm, IHostFactories hostFactories, CancellationToken cancellationToken)
        {
            Requires.NotNull(realm, "realm");
            Requires.NotNull(hostFactories, "hostFactories");

            XrdsDocument xrds = await realm.DiscoverAsync(hostFactories, false, cancellationToken);

            if (xrds == null)
            {
                return(Enumerable.Empty <Uri>());
            }
            else
            {
                return(xrds.FindRelyingPartyIcons());
            }
        }
Esempio n. 47
0
		/// <summary>
		/// Initializes a new instance of the <see cref="OAuth2ChannelBase" /> class.
		/// </summary>
		/// <param name="messageTypes">The message types that are received by this channel.</param>
		/// <param name="channelBindingElements">The binding elements to use in sending and receiving messages.
		/// The order they are provided is used for outgoing messgaes, and reversed for incoming messages.</param>
		/// <param name="hostFactories">The host factories.</param>
		internal OAuth2ChannelBase(Type[] messageTypes, IChannelBindingElement[] channelBindingElements = null, IHostFactories hostFactories = null)
			: base(Requires.NotNull(messageTypes, "messageTypes"), Versions, hostFactories ?? new OAuth.DefaultOAuthHostFactories(), channelBindingElements ?? new IChannelBindingElement[0]) {
		}
Esempio n. 48
0
 internal TestChannel(IHostFactories hostFactories = null)
     : this(new TestMessageFactory(), new IChannelBindingElement[0], hostFactories ?? new DefaultOpenIdHostFactories())
 {
 }
Esempio n. 49
0
		/// <summary>
		/// Initializes a new instance of the <see cref="WebServerClient" /> class.
		/// </summary>
		/// <param name="authorizationServer">The authorization server.</param>
		/// <param name="clientIdentifier">The client identifier.</param>
		/// <param name="clientSecret">The client secret.</param>
		/// <param name="hostFactories">The host factories.</param>
		public WebServerClient(AuthorizationServerDescription authorizationServer, string clientIdentifier = null, string clientSecret = null, IHostFactories hostFactories = null)
			: this(authorizationServer, clientIdentifier, DefaultSecretApplicator(clientSecret), hostFactories) {
		}
		/// <summary>
		/// Gets a value indicating whether verification of the return URL claimed by the Relying Party
		/// succeeded.
		/// </summary>
		/// <param name="hostFactories">The host factories.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <returns>
		/// Result of realm discovery.
		/// </returns>
		/// <remarks>
		/// Return URL verification is only attempted if this property is queried.
		/// The result of the verification is cached per request so calling this
		/// property getter multiple times in one request is not a performance hit.
		/// See OpenID Authentication 2.0 spec section 9.2.1.
		/// </remarks>
		public async Task<RelyingPartyDiscoveryResult> IsReturnUrlDiscoverableAsync(IHostFactories hostFactories, CancellationToken cancellationToken = default(CancellationToken)) {
			Requires.NotNull(hostFactories, "hostFactories");
			if (!this.realmDiscoveryResult.HasValue) {
				this.realmDiscoveryResult = await this.IsReturnUrlDiscoverableCoreAsync(hostFactories, cancellationToken);
			}

			return this.realmDiscoveryResult.Value;
		}
Esempio n. 51
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OpenIdProvider" /> class.
 /// </summary>
 /// <param name="applicationStore">The application store to use.  Cannot be null.</param>
 /// <param name="hostFactories">The host factories.</param>
 public OpenIdProvider(ICryptoKeyAndNonceStore applicationStore, IHostFactories hostFactories = null)
     : this((INonceStore)applicationStore, (ICryptoKeyStore)applicationStore, hostFactories)
 {
     Requires.NotNull(applicationStore, "applicationStore");
 }
Esempio n. 52
0
		internal TestChannel(MessageDescriptionCollection messageDescriptions, IHostFactories hostFactories = null)
			: this(hostFactories) {
			this.MessageDescriptions = messageDescriptions;
		}
		/// <summary>
		/// Gets a value indicating whether verification of the return URL claimed by the Relying Party
		/// succeeded.
		/// </summary>
		/// <param name="hostFactories">The host factories.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <returns>
		/// Result of realm discovery.
		/// </returns>
		private async Task<RelyingPartyDiscoveryResult> IsReturnUrlDiscoverableCoreAsync(IHostFactories hostFactories, CancellationToken cancellationToken) {
			Requires.NotNull(hostFactories, "hostFactories");
			ErrorUtilities.VerifyInternal(this.Realm != null, "Realm should have been read or derived by now.");

			try {
				if (this.SecuritySettings.RequireSsl && this.Realm.Scheme != Uri.UriSchemeHttps) {
					Logger.OpenId.WarnFormat("RP discovery failed because RequireSsl is true and RP discovery would begin at insecure URL {0}.", this.Realm);
					return RelyingPartyDiscoveryResult.NoServiceDocument;
				}

				var returnToEndpoints = await this.Realm.DiscoverReturnToEndpointsAsync(hostFactories, false, cancellationToken);
				if (returnToEndpoints == null) {
					return RelyingPartyDiscoveryResult.NoServiceDocument;
				}

				foreach (var returnUrl in returnToEndpoints) {
					Realm discoveredReturnToUrl = returnUrl.ReturnToEndpoint;

					// The spec requires that the return_to URLs given in an RPs XRDS doc
					// do not contain wildcards.
					if (discoveredReturnToUrl.DomainWildcard) {
						Logger.Yadis.WarnFormat("Realm {0} contained return_to URL {1} which contains a wildcard, which is not allowed.", Realm, discoveredReturnToUrl);
						continue;
					}

					// Use the same rules as return_to/realm matching to check whether this
					// URL fits the return_to URL we were given.
					if (discoveredReturnToUrl.Contains(this.RequestMessage.ReturnTo)) {
						// no need to keep looking after we find a match
						return RelyingPartyDiscoveryResult.Success;
					}
				}
			} catch (ProtocolException ex) {
				// Don't do anything else.  We quietly fail at return_to verification and return false.
				Logger.Yadis.InfoFormat("Relying party discovery at URL {0} failed.  {1}", Realm, ex);
				return RelyingPartyDiscoveryResult.NoServiceDocument;
			} catch (WebException ex) {
				// Don't do anything else.  We quietly fail at return_to verification and return false.
				Logger.Yadis.InfoFormat("Relying party discovery at URL {0} failed.  {1}", Realm, ex);
				return RelyingPartyDiscoveryResult.NoServiceDocument;
			}

			return RelyingPartyDiscoveryResult.NoMatchingReturnTo;
		}
Esempio n. 54
0
        /// <summary>
        /// Initializes a new instance of the <see cref="OpenIdProvider" /> class.
        /// </summary>
        /// <param name="nonceStore">The nonce store to use.  Cannot be null.</param>
        /// <param name="cryptoKeyStore">The crypto key store.  Cannot be null.</param>
        /// <param name="hostFactories">The host factories.</param>
        private OpenIdProvider(INonceStore nonceStore, ICryptoKeyStore cryptoKeyStore, IHostFactories hostFactories)
        {
            Requires.NotNull(nonceStore, "nonceStore");
            Requires.NotNull(cryptoKeyStore, "cryptoKeyStore");

            this.SecuritySettings             = OpenIdElement.Configuration.Provider.SecuritySettings.CreateSecuritySettings();
            this.behaviors.CollectionChanged += this.OnBehaviorsChanged;
            foreach (var behavior in OpenIdElement.Configuration.Provider.Behaviors.CreateInstances(false, null))
            {
                this.behaviors.Add(behavior);
            }

            this.AssociationStore  = new SwitchingAssociationStore(cryptoKeyStore, this.SecuritySettings);
            this.Channel           = new OpenIdProviderChannel(this.AssociationStore, nonceStore, this.SecuritySettings, hostFactories);
            this.CryptoKeyStore    = cryptoKeyStore;
            this.discoveryServices = new IdentifierDiscoveryServices(this);

            Reporting.RecordFeatureAndDependencyUse(this, nonceStore);
        }
Esempio n. 55
0
 /// <summary>
 /// Searches for an XRDS document at the realm URL, and if found, searches
 /// for a description of a relying party endpoints (OpenId login pages).
 /// </summary>
 /// <param name="hostFactories">The host factories.</param>
 /// <param name="allowRedirects">Whether redirects may be followed when discovering the Realm.
 /// This may be true when creating an unsolicited assertion, but must be
 /// false when performing return URL verification per 2.0 spec section 9.2.1.</param>
 /// <param name="cancellationToken">The cancellation token.</param>
 /// <returns>
 /// The details of the endpoints if found, otherwise null.
 /// </returns>
 internal override Task <IEnumerable <RelyingPartyEndpointDescription> > DiscoverReturnToEndpointsAsync(IHostFactories hostFactories, bool allowRedirects, CancellationToken cancellationToken)
 {
     return(Task.FromResult <IEnumerable <RelyingPartyEndpointDescription> >(this.relyingPartyDescriptions));
 }
Esempio n. 56
0
        /// <summary>
        /// Initializes a new instance of the <see cref="OpenIdChannel" /> class.
        /// </summary>
        /// <param name="messageTypeProvider">A class prepared to analyze incoming messages and indicate what concrete
        /// message types can deserialize from it.</param>
        /// <param name="bindingElements">The binding elements to use in sending and receiving messages.</param>
        /// <param name="hostFactories">The host factories.</param>
        protected OpenIdChannel(IMessageFactory messageTypeProvider, IChannelBindingElement[] bindingElements, IHostFactories hostFactories)
            : base(messageTypeProvider, bindingElements, hostFactories ?? new DefaultOpenIdHostFactories())
        {
            Requires.NotNull(messageTypeProvider, "messageTypeProvider");

            // Customize the binding element order, since we play some tricks for higher
            // security and backward compatibility with older OpenID versions.
            var outgoingBindingElements = new List <IChannelBindingElement>(bindingElements);
            var incomingBindingElements = new List <IChannelBindingElement>(bindingElements);

            incomingBindingElements.Reverse();

            // Customize the order of the incoming elements by moving the return_to elements in front.
            var backwardCompatibility = incomingBindingElements.OfType <BackwardCompatibilityBindingElement>().SingleOrDefault();
            var returnToSign          = incomingBindingElements.OfType <ReturnToSignatureBindingElement>().SingleOrDefault();

            if (backwardCompatibility != null)
            {
                incomingBindingElements.MoveTo(0, backwardCompatibility);
            }
            if (returnToSign != null)
            {
                // Yes, this is intentionally, shifting the backward compatibility
                // binding element to second position.
                incomingBindingElements.MoveTo(0, returnToSign);
            }

            this.CustomizeBindingElementOrder(outgoingBindingElements, incomingBindingElements);
        }