Inheritance: DotNetOpenAuth.OpenId.Messages.IndirectResponseBase, ITamperResistantOpenIdMessage, IProtocolMessageWithExtensions
		internal AnonymousRequest(OpenIdProvider provider, SignedResponseRequest request)
			: base(provider, request) {
			Contract.Requires<ArgumentNullException>(provider != null);
			Contract.Requires<ArgumentException>(!(request is CheckIdRequest), "Instantiate " + typeof(AuthenticationRequest).Name + " to handle this kind of message.");

			this.positiveResponse = new IndirectSignedResponse(request);
		}
		internal AnonymousRequest(OpenIdProvider provider, SignedResponseRequest request)
			: base(provider, request) {
			Contract.Requires<ArgumentNullException>(provider != null);
			Contract.Requires<ArgumentException>(!(request is CheckIdRequest));

			this.positiveResponse = new IndirectSignedResponse(request);
		}
		public override void SetUp() {
			base.SetUp();

			IndirectSignedResponse responseMessage = new IndirectSignedResponse(Protocol.Default.Version, RPUri);
			this.extensions = responseMessage.Extensions;
			this.response = new DotNetOpenAuth.OpenId.RelyingParty.PositiveAnonymousResponse(responseMessage);
		}
Beispiel #4
0
		internal AnonymousRequest(OpenIdProvider provider, SignedResponseRequest request)
			: base(provider, request) {
			Requires.NotNull(provider, "provider");
			Requires.True(!(request is CheckIdRequest), "request");

			this.positiveResponse = new IndirectSignedResponse(request);
		}
		public void ProviderTest() {
			var responseMessage = new IndirectSignedResponse(Protocol.V20.Version, this.returnTo);
			responseMessage.ProviderEndpoint = OPUri;
			var response = new PositiveAnonymousResponse(responseMessage);
			Assert.IsNotNull(response.Provider);
			Assert.AreEqual(OPUri, response.Provider.Uri);
			Assert.AreEqual(responseMessage.Version, response.Provider.Version);
		}
        internal AnonymousRequest(OpenIdProvider provider, SignedResponseRequest request)
            : base(provider, request)
        {
            Contract.Requires(provider != null);
            Contract.Requires(!(request is CheckIdRequest), "Instantiate " + typeof(AuthenticationRequest).Name + " to handle this kind of message.");
            ErrorUtilities.VerifyInternal(!(request is CheckIdRequest), "Instantiate {0} to handle this kind of message.", typeof(AuthenticationRequest).Name);

            this.positiveResponse = new IndirectSignedResponse(request);
        }
        /// <summary>
        /// Analyzes an incoming request message payload to discover what kind of
        /// message is embedded in it and returns the type, or null if no match is found.
        /// </summary>
        /// <param name="recipient">The intended or actual recipient of the request message.</param>
        /// <param name="fields">The name/value pairs that make up the message payload.</param>
        /// <returns>
        /// A newly instantiated <see cref="IProtocolMessage"/>-derived object that this message can
        /// deserialize to.  Null if the request isn't recognized as a valid protocol message.
        /// </returns>
        public IDirectedProtocolMessage GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary<string, string> fields)
        {
            ErrorUtilities.VerifyArgumentNotNull(recipient, "recipient");
            ErrorUtilities.VerifyArgumentNotNull(fields, "fields");

            RequestBase message = null;

            // Discern the OpenID version of the message.
            Protocol protocol = Protocol.V11;
            string ns;
            if (fields.TryGetValue(Protocol.V20.openid.ns, out ns)) {
                ErrorUtilities.VerifyProtocol(string.Equals(ns, Protocol.OpenId2Namespace, StringComparison.Ordinal), MessagingStrings.UnexpectedMessagePartValue, Protocol.V20.openid.ns, ns);
                protocol = Protocol.V20;
            }

            string mode;
            if (fields.TryGetValue(protocol.openid.mode, out mode)) {
                if (string.Equals(mode, protocol.Args.Mode.associate)) {
                    if (fields.ContainsKey(protocol.openid.dh_consumer_public)) {
                        message = new AssociateDiffieHellmanRequest(protocol.Version, recipient.Location);
                    } else {
                        message = new AssociateUnencryptedRequest(protocol.Version, recipient.Location);
                    }
                } else if (string.Equals(mode, protocol.Args.Mode.checkid_setup) ||
                    string.Equals(mode, protocol.Args.Mode.checkid_immediate)) {
                    AuthenticationRequestMode authMode = string.Equals(mode, protocol.Args.Mode.checkid_immediate) ? AuthenticationRequestMode.Immediate : AuthenticationRequestMode.Setup;
                    if (fields.ContainsKey(protocol.openid.identity)) {
                        message = new CheckIdRequest(protocol.Version, recipient.Location, authMode);
                    } else {
                        ErrorUtilities.VerifyProtocol(!fields.ContainsKey(protocol.openid.claimed_id), OpenIdStrings.IdentityAndClaimedIdentifierMustBeBothPresentOrAbsent);
                        message = new SignedResponseRequest(protocol.Version, recipient.Location, authMode);
                    }
                } else if (string.Equals(mode, protocol.Args.Mode.cancel) ||
                    (string.Equals(mode, protocol.Args.Mode.setup_needed) && (protocol.Version.Major >= 2 || fields.ContainsKey(protocol.openid.user_setup_url)))) {
                    message = new NegativeAssertionResponse(protocol.Version, recipient.Location, mode);
                } else if (string.Equals(mode, protocol.Args.Mode.id_res)) {
                    if (fields.ContainsKey(protocol.openid.identity)) {
                        message = new PositiveAssertionResponse(protocol.Version, recipient.Location);
                    } else {
                        ErrorUtilities.VerifyProtocol(!fields.ContainsKey(protocol.openid.claimed_id), OpenIdStrings.IdentityAndClaimedIdentifierMustBeBothPresentOrAbsent);
                        message = new IndirectSignedResponse(protocol.Version, recipient.Location);
                    }
                } else if (string.Equals(mode, protocol.Args.Mode.check_authentication)) {
                    message = new CheckAuthenticationRequest(protocol.Version, recipient.Location);
                } else if (string.Equals(mode, protocol.Args.Mode.error)) {
                    message = new IndirectErrorResponse(protocol.Version, recipient.Location);
                } else {
                    ErrorUtilities.ThrowProtocol(MessagingStrings.UnexpectedMessagePartValue, protocol.openid.mode, mode);
                }
            }

            if (message != null) {
                message.SetAsIncoming();
            }

            return message;
        }
		public override void SetUp() {
			base.SetUp();

			this.protocol = Protocol.V20;
			this.request = new CheckIdRequest(this.protocol.Version, OPUri, AuthenticationRequestMode.Setup);
			this.request.ReturnTo = RPUri;
			this.response = new IndirectSignedResponse(this.request);

			this.unsolicited = new IndirectSignedResponse(this.protocol.Version, RPUri);
		}
		public void CtorAndProperties() {
			var responseMessage = new IndirectSignedResponse(Protocol.V20.Version, this.returnTo);
			var ext = new ClaimsResponse();
			responseMessage.Extensions.Add(ext);
			var response = new PositiveAnonymousResponse(responseMessage);
			Assert.AreEqual(AuthenticationStatus.ExtensionsOnly, response.Status);
			Assert.AreSame(responseMessage, response.Response);
			Assert.IsNull(response.ClaimedIdentifier);
			Assert.IsNull(response.FriendlyIdentifierForDisplay);
			Assert.IsNull(response.Exception);
			Assert.IsNull(response.Provider);
			Assert.AreSame(ext, response.GetUntrustedExtension<ClaimsResponse>());
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="CheckAuthenticationRequest"/> class
		/// based on the contents of some signed message whose signature must be verified.
		/// </summary>
		/// <param name="message">The message whose signature should be verified.</param>
		/// <param name="channel">The channel.  This is used only within the constructor and is not stored in a field.</param>
		internal CheckAuthenticationRequest(IndirectSignedResponse message, Channel channel)
			: base(message.Version, message.ProviderEndpoint, GetProtocolConstant(message.Version, p => p.Args.Mode.check_authentication), MessageTransport.Direct) {
			Requires.NotNull(channel, "channel");

			// Copy all message parts from the id_res message into this one,
			// except for the openid.mode parameter.
			MessageDictionary checkPayload = channel.MessageDescriptions.GetAccessor(message, true);
			MessageDictionary thisPayload = channel.MessageDescriptions.GetAccessor(this);
			foreach (var pair in checkPayload) {
				if (!string.Equals(pair.Key, this.Protocol.openid.mode)) {
					thisPayload[pair.Key] = pair.Value;
				}
			}
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="CheckAuthenticationResponseProvider"/> class.
		/// </summary>
		/// <param name="request">The request that this message is responding to.</param>
		/// <param name="provider">The OpenID Provider that is preparing to send this response.</param>
		internal CheckAuthenticationResponseProvider(CheckAuthenticationRequest request, OpenIdProvider provider)
			: base(request.Version, request) {
			Requires.NotNull(provider, "provider");

			// The channel's binding elements have already set the request's IsValid property
			// appropriately.  We just copy it into the response message.
			this.IsValid = request.IsValid;

			// Confirm the RP should invalidate the association handle only if the association
			// 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, false, invalidateHandle)) {
				this.InvalidateHandle = invalidateHandle;
			}
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="CheckAuthenticationResponse"/> class
		/// for use by the Provider.
		/// </summary>
		/// <param name="request">The request that this message is responding to.</param>
		/// <param name="provider">The OpenID Provider that is preparing to send this response.</param>
		internal CheckAuthenticationResponse(CheckAuthenticationRequest request, OpenIdProvider provider)
			: base(request.Version, request) {
			Contract.Requires<ArgumentNullException>(provider != null);

			// The channel's binding elements have already set the request's IsValid property
			// appropriately.  We just copy it into the response message.
			this.IsValid = request.IsValid;

			// Confirm the RP should invalidate the association handle only if the association
			// really doesn't exist.  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.GetAssociation(AssociationRelyingPartyType.Smart, invalidateHandle) == null) {
				this.InvalidateHandle = invalidateHandle;
			}
		}
        /// <summary>
        /// Initializes a new instance of the <see cref="CheckAuthenticationRequest"/> class
        /// based on the contents of some signed message whose signature must be verified.
        /// </summary>
        /// <param name="message">The message whose signature should be verified.</param>
        internal CheckAuthenticationRequest(IndirectSignedResponse message)
            : base(message.Version, message.ProviderEndpoint, GetProtocolConstant(message.Version, p => p.Args.Mode.check_authentication), MessageTransport.Direct)
        {
            // Copy all message parts from the id_res message into this one,
            // except for the openid.mode parameter.
            MessageDictionary checkPayload = new MessageDictionary(message);
            MessageDictionary thisPayload  = new MessageDictionary(this);

            foreach (var pair in checkPayload)
            {
                if (!string.Equals(pair.Key, this.Protocol.openid.mode))
                {
                    thisPayload[pair.Key] = pair.Value;
                }
            }
        }
Beispiel #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CheckAuthenticationRequest"/> class
        /// based on the contents of some signed message whose signature must be verified.
        /// </summary>
        /// <param name="message">The message whose signature should be verified.</param>
        /// <param name="channel">The channel.  This is used only within the constructor and is not stored in a field.</param>
        internal CheckAuthenticationRequest(IndirectSignedResponse message, Channel channel)
            : base(message.Version, message.ProviderEndpoint, GetProtocolConstant(message.Version, p => p.Args.Mode.check_authentication), MessageTransport.Direct)
        {
            Contract.Requires <ArgumentNullException>(channel != null);

            // Copy all message parts from the id_res message into this one,
            // except for the openid.mode parameter.
            MessageDictionary checkPayload = channel.MessageDescriptions.GetAccessor(message, true);
            MessageDictionary thisPayload  = channel.MessageDescriptions.GetAccessor(this);

            foreach (var pair in checkPayload)
            {
                if (!string.Equals(pair.Key, this.Protocol.openid.mode))
                {
                    thisPayload[pair.Key] = pair.Value;
                }
            }
        }
		public void SignaturesMatchKnownGood() {
			Protocol protocol = Protocol.V20;
			var settings = new ProviderSecuritySettings();
			var store = new AssociationMemoryStore<AssociationRelyingPartyType>();
			byte[] associationSecret = Convert.FromBase64String("rsSwv1zPWfjPRQU80hciu8FPDC+GONAMJQ/AvSo1a2M=");
			Association association = HmacShaAssociation.Create("mock", associationSecret, TimeSpan.FromDays(1));
			store.StoreAssociation(AssociationRelyingPartyType.Smart, association);
			SigningBindingElement signer = new SigningBindingElement(store, settings);
			signer.Channel = new TestChannel(this.MessageDescriptions);

			IndirectSignedResponse message = new IndirectSignedResponse(protocol.Version, new Uri("http://rp"));
			ITamperResistantOpenIdMessage signedMessage = message;
			message.ProviderEndpoint = new Uri("http://provider");
			signedMessage.UtcCreationDate = DateTime.Parse("1/1/2009");
			signedMessage.AssociationHandle = association.Handle;
			Assert.IsNotNull(signer.ProcessOutgoingMessage(message));
			Assert.AreEqual("o9+uN7qTaUS9v0otbHTuNAtbkpBm14+es9QnNo6IHD4=", signedMessage.Signature);
		}
        /// <summary>
        /// Initializes a new instance of the <see cref="CheckAuthenticationResponse"/> class
        /// for use by the Provider.
        /// </summary>
        /// <param name="request">The request that this message is responding to.</param>
        /// <param name="provider">The OpenID Provider that is preparing to send this response.</param>
        internal CheckAuthenticationResponse(CheckAuthenticationRequest request, OpenIdProvider provider)
            : base(request.Version, request)
        {
            ErrorUtilities.VerifyArgumentNotNull(provider, "provider");

            // The channel's binding elements have already set the request's IsValid property
            // appropriately.  We just copy it into the response message.
            this.IsValid = request.IsValid;

            // Confirm the RP should invalidate the association handle only if the association
            // really doesn't exist.  OpenID 2.0 section 11.4.2.2.
            IndirectSignedResponse signedResponse = new IndirectSignedResponse(request);
            string invalidateHandle = ((ITamperResistantOpenIdMessage)signedResponse).InvalidateHandle;

            if (invalidateHandle != null && provider.AssociationStore.GetAssociation(AssociationRelyingPartyType.Smart, invalidateHandle) == null)
            {
                this.InvalidateHandle = invalidateHandle;
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="CheckAuthenticationResponseProvider"/> class.
        /// </summary>
        /// <param name="request">The request that this message is responding to.</param>
        /// <param name="provider">The OpenID Provider that is preparing to send this response.</param>
        internal CheckAuthenticationResponseProvider(CheckAuthenticationRequest request, OpenIdProvider provider)
            : base(request.Version, request)
        {
            Requires.NotNull(provider, "provider");

            // The channel's binding elements have already set the request's IsValid property
            // appropriately.  We just copy it into the response message.
            this.IsValid = request.IsValid;

            // Confirm the RP should invalidate the association handle only if the association
            // 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, false, invalidateHandle))
            {
                this.InvalidateHandle = invalidateHandle;
            }
        }
		public void SignaturesMatchKnownGood() {
			Protocol protocol = Protocol.V20;
			var settings = new ProviderSecuritySettings();
			var cryptoStore = new MemoryCryptoKeyStore();
			byte[] associationSecret = Convert.FromBase64String("rsSwv1zPWfjPRQU80hciu8FPDC+GONAMJQ/AvSo1a2M=");
			string handle = "mock";
			cryptoStore.StoreKey(ProviderAssociationKeyStorage.SharedAssociationBucket, handle, new CryptoKey(associationSecret, DateTime.UtcNow.AddDays(1)));

			var store = new ProviderAssociationKeyStorage(cryptoStore);
			SigningBindingElement signer = new ProviderSigningBindingElement(store, settings);
			signer.Channel = new TestChannel(this.MessageDescriptions);

			IndirectSignedResponse message = new IndirectSignedResponse(protocol.Version, new Uri("http://rp"));
			ITamperResistantOpenIdMessage signedMessage = message;
			message.ProviderEndpoint = new Uri("http://provider");
			signedMessage.UtcCreationDate = DateTime.Parse("1/1/2009");
			signedMessage.AssociationHandle = handle;
			Assert.IsNotNull(signer.ProcessOutgoingMessage(message));
			Assert.AreEqual("o9+uN7qTaUS9v0otbHTuNAtbkpBm14+es9QnNo6IHD4=", signedMessage.Signature);
		}
        public void GetReturnToArgumentAndNames()
        {
            UriBuilder returnToBuilder = new UriBuilder(this.response.ReturnTo);
            returnToBuilder.AppendQueryArgs(new Dictionary<string, string> { { "a", "b" } });
            this.request.ReturnTo = returnToBuilder.Uri;

            // First pretend that the return_to args were signed.
            this.response = new IndirectSignedResponse(this.request);
            this.response.ReturnToParametersSignatureValidated = true;
            Assert.AreEqual(1, this.response.GetReturnToParameterNames().Count());
            Assert.IsTrue(this.response.GetReturnToParameterNames().Contains("a"));
            Assert.AreEqual("b", this.response.GetReturnToArgument("a"));

            // Now simulate them NOT being signed.  They should still be visible at this level.
            this.response = new IndirectSignedResponse(this.request);
            this.response.ReturnToParametersSignatureValidated = false;
            Assert.AreEqual(1, this.response.GetReturnToParameterNames().Count());
            Assert.IsTrue(this.response.GetReturnToParameterNames().Contains("a"));
            Assert.AreEqual("b", this.response.GetReturnToArgument("a"));
        }
		public void SignedResponsesIncludeExtraDataInSignature() {
			Protocol protocol = Protocol.Default;
			SigningBindingElement sbe = new ProviderSigningBindingElement(new ProviderAssociationHandleEncoder(new MemoryCryptoKeyStore()), new ProviderSecuritySettings());
			sbe.Channel = new TestChannel(this.MessageDescriptions);
			IndirectSignedResponse response = new IndirectSignedResponse(protocol.Version, RPUri);
			response.ReturnTo = RPUri;
			response.ProviderEndpoint = OPUri;

			response.ExtraData["someunsigned"] = "value";
			response.ExtraData["openid.somesigned"] = "value";

			Assert.IsNotNull(sbe.ProcessOutgoingMessage(response));
			ITamperResistantOpenIdMessage signedResponse = (ITamperResistantOpenIdMessage)response;

			// Make sure that the extra parameters are signed.
			// Since the signing algorithm only allows for signing parameters that start with
			// 'openid.', other parameters should not be signed.
			Assert.IsNotNull(signedResponse.SignedParameterOrder);
			string[] signedParameters = signedResponse.SignedParameterOrder.Split(',');
			Assert.IsTrue(signedParameters.Contains("somesigned"));
			Assert.IsFalse(signedParameters.Contains("someunsigned"));
		}
        /// <summary>
        /// Creates a response message with one extensions.
        /// </summary>
        /// <param name="protocol">The protocol to construct the message with.</param>
        /// <returns>The message ready to send from OP to RP.</returns>
        private IndirectSignedResponse CreateResponseWithExtensions(Protocol protocol)
        {
            ErrorUtilities.VerifyArgumentNotNull(protocol, "protocol");

            IndirectSignedResponse response = new IndirectSignedResponse(protocol.Version, RPUri);
            response.ProviderEndpoint = OPUri;
            response.Extensions.Add(new MockOpenIdExtension("pv", "ev"));
            return response;
        }
		public void MissingSignedParameter() {
			var cryptoStore = new MemoryCryptoKeyStore();
			byte[] associationSecret = Convert.FromBase64String("rsSwv1zPWfjPRQU80hciu8FPDC+GONAMJQ/AvSo1a2M=");
			string handle = "{634477555066085461}{TTYcIg==}{32}";
			cryptoStore.StoreKey(ProviderAssociationKeyStorage.PrivateAssociationBucket, handle, new CryptoKey(associationSecret, DateTime.UtcNow.AddDays(1)));

			var signer = new ProviderSigningBindingElement(new ProviderAssociationKeyStorage(cryptoStore), new ProviderSecuritySettings());
			var testChannel = new TestChannel(new OpenIdProviderMessageFactory());
			signer.Channel = testChannel;

			var buggyRPMessage = new Dictionary<string, string>() {
				{ "openid.assoc_handle", "{634477555066085461}{TTYcIg==}{32}" },
				{ "openid.claimed_id", "https://openid.stackexchange.com/user/f5e91123-e5b4-43c5-871f-5f276c75d31a" },
				{ "openid.identity", "https://openid.stackexchange.com/user/f5e91123-e5b4-43c5-871f-5f276c75d31a" },
				{ "openid.mode", "check_authentication" },
				{ "openid.op_endpoint", "https://openid.stackexchange.com/openid/provider" },
				{ "openid.response_nonce", "2011-08-01T00:32:10Zvdyt3efw" },
				{ "openid.return_to", "http://openid-consumer.appspot.com/finish?session_id=1543025&janrain_nonce=2011-08-01T00%3A32%3A09ZIPGz7D" },
				{ "openid.sig", "b0Rll6Kt1KKBWWBEg/qBvW3sQYtmhOUmpI0/UREBVZ0=" },
				{ "openid.signed", "claimed_id,identity,assoc_handle,op_endpoint,return_to,response_nonce,ns.sreg,sreg.email,sreg.fullname" },
				{ "openid.sreg.email", "*****@*****.**" },
				{ "openid.sreg.fullname", "Kevin K Montrose" },
			};
			var message = (CheckAuthenticationRequest)testChannel.Receive(buggyRPMessage, new MessageReceivingEndpoint(OPUri, HttpDeliveryMethods.PostRequest));
			var originalResponse = new IndirectSignedResponse(message, signer.Channel);
			signer.ProcessIncomingMessage(originalResponse);
		}
		/// <summary>
		/// Creates a response message with one extensions.
		/// </summary>
		/// <param name="protocol">The protocol to construct the message with.</param>
		/// <returns>The message ready to send from OP to RP.</returns>
		private IndirectSignedResponse CreateResponseWithExtensions(Protocol protocol) {
			Requires.NotNull(protocol, "protocol");

			var response = new IndirectSignedResponse(protocol.Version, RPUri);
			response.ProviderEndpoint = OPUri;
			response.Extensions.Add(new MockOpenIdExtension("pv", "ev"));
			return response;
		}
Beispiel #24
0
		/// <summary>
		/// Verifies the integrity and applicability of an incoming message.
		/// </summary>
		/// <param name="message">The message just received.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <returns>
		/// A task that completes with the asynchronous operation.
		/// </returns>
		/// <exception cref="ProtocolException">Thrown when the message is somehow invalid, except for check_authentication messages.
		/// This can be due to tampering, replay attack or expiration, among other things.</exception>
		protected override async Task ProcessIncomingMessageAsync(IProtocolMessage message, CancellationToken cancellationToken) {
			var checkAuthRequest = message as CheckAuthenticationRequest;
			if (checkAuthRequest != null) {
				IndirectSignedResponse originalResponse = new IndirectSignedResponse(checkAuthRequest, this);
				try {
					await base.ProcessIncomingMessageAsync(originalResponse, cancellationToken);
					checkAuthRequest.IsValid = true;
				} catch (ProtocolException) {
					checkAuthRequest.IsValid = false;
				}
			} else {
				await base.ProcessIncomingMessageAsync(message, cancellationToken);
			}

			// Convert an OpenID indirect error message, which we never expect
			// between two good OpenID implementations, into an exception.
			// We don't process DirectErrorResponse because associate negotiations
			// commonly get a derivative of that message type and handle it.
			var errorMessage = message as IndirectErrorResponse;
			if (errorMessage != null) {
				string exceptionMessage = string.Format(
					CultureInfo.CurrentCulture,
					OpenIdStrings.IndirectErrorFormattedMessage,
					errorMessage.ErrorMessage,
					errorMessage.Contact,
					errorMessage.Reference);
				throw new ProtocolException(exceptionMessage, message);
			}
		}
		/// <summary>
		/// Determines whether the relying party sending an authentication request is
		/// vulnerable to replay attacks.
		/// </summary>
		/// <param name="request">The request message from the Relying Party.  Useful, but may be null for conservative estimate results.</param>
		/// <param name="response">The response message to be signed.</param>
		/// <returns>
		/// 	<c>true</c> if the relying party is vulnerable; otherwise, <c>false</c>.
		/// </returns>
		private static bool IsRelyingPartyVulnerableToReplays(SignedResponseRequest request, IndirectSignedResponse response) {
			Contract.Requires<ArgumentNullException>(response != null);

			// OpenID 2.0 includes replay protection as part of the protocol.
			if (response.Version.Major >= 2) {
				return false;
			}

			// This library's RP may be on the remote end, and may be using 1.x merely because
			// discovery on the Claimed Identifier suggested this was a 1.x OP.  
			// Since this library's RP has a built-in request_nonce parameter for replay
			// protection, we'll allow for that.
			var returnToArgs = HttpUtility.ParseQueryString(response.ReturnTo.Query);
			if (!string.IsNullOrEmpty(returnToArgs[ReturnToNonceBindingElement.NonceParameter])) {
				return false;
			}

			// If the OP endpoint _AND_ RP return_to URL uses HTTPS then no one
			// can steal and replay the positive assertion.
			// We can only ascertain this if the request message was handed to us
			// so we know what our own OP endpoint is.  If we don't have a request
			// message, then we'll default to assuming it's insecure.
			if (request != null) {
				if (request.Recipient.IsTransportSecure() && response.Recipient.IsTransportSecure()) {
					return false;
				}
			}

			// Nothing left to protect against replays.  RP is vulnerable.
			return true;
		}
		/// <summary>
		/// Creates a response message with one extensions.
		/// </summary>
		/// <param name="protocol">The protocol to construct the message with.</param>
		/// <returns>The message ready to send from OP to RP.</returns>
		private IndirectSignedResponse CreateResponseWithExtensions(Protocol protocol) {
			Contract.Requires<ArgumentNullException>(protocol != null);

			IndirectSignedResponse response = new IndirectSignedResponse(protocol.Version, RPUri);
			response.ProviderEndpoint = OPUri;
			response.Extensions.Add(new MockOpenIdExtension("pv", "ev"));
			return response;
		}