/// <summary>
		/// Initializes a new instance of the <see cref="HostProcessedRequest"/> class.
		/// </summary>
		/// <param name="provider">The provider that received the request.</param>
		/// <param name="request">The incoming request message.</param>
		protected HostProcessedRequest(OpenIdProvider provider, SignedResponseRequest request)
			: base(request, provider.SecuritySettings) {
			Contract.Requires<ArgumentNullException>(provider != null);

			this.negativeResponse = new NegativeAssertionResponse(request, provider.Channel);
			Reporting.RecordEventOccurrence(this, request.Realm);
		}
		public void UserSetupUrlSetForV1Immediate() {
			var immediateRequestV1 = new CheckIdRequest(Protocol.V10.Version, OPUri, AuthenticationRequestMode.Immediate);
			immediateRequestV1.ReturnTo = RPUri;
			var response = new NegativeAssertionResponse(immediateRequestV1);
			response.UserSetupUrl = new Uri("http://usersetup");
			response.EnsureValidMessage();
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="HostProcessedRequest"/> class.
		/// </summary>
		/// <param name="provider">The provider that received the request.</param>
		/// <param name="request">The incoming request message.</param>
		protected HostProcessedRequest(OpenIdProvider provider, SignedResponseRequest request)
			: base(request, provider.SecuritySettings) {
			Requires.NotNull(provider, "provider");

			this.negativeResponse = new NegativeAssertionResponse(request, provider.Channel);
			Reporting.RecordEventOccurrence(this, request.Realm);
		}
        /// <summary>
        /// Initializes a new instance of the <see cref="HostProcessedRequest"/> class.
        /// </summary>
        /// <param name="provider">The provider that received the request.</param>
        /// <param name="request">The incoming request message.</param>
        protected HostProcessedRequest(OpenIdProvider provider, SignedResponseRequest request)
            : base(request, provider.SecuritySettings)
        {
            Contract.Requires(provider != null);

            this.negativeResponse = new NegativeAssertionResponse(request, provider.Channel);
        }
		public override void SetUp() {
			base.SetUp();

			this.protocol = Protocol.Default;
			this.responseMessage = new NegativeAssertionResponse(this.protocol.Version, RPUri, this.protocol.Args.Mode.cancel);
			this.responseMessage.ExtraData[AuthenticationRequest.UserSuppliedIdentifierParameterName] = UserSuppliedIdentifier;
			this.response = new NegativeAuthenticationResponse(this.responseMessage);
		}
        /// <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;
        }
Exemple #7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NegativeAssertionResponse" /> class.
        /// </summary>
        /// <param name="request">The request that the relying party sent.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <param name="channel">The channel to use to simulate construction of the user_setup_url, if applicable.  May be null, but the user_setup_url will not be constructed.</param>
        /// <returns>The negative assertion message that will indicate failure for the user to authenticate or an unwillingness to log into the relying party.</returns>
        internal static async Task <NegativeAssertionResponse> CreateAsync(SignedResponseRequest request, CancellationToken cancellationToken, Channel channel = null)
        {
            var result = new NegativeAssertionResponse(request);

            // If appropriate, and when we're provided with a channel to do it,
            // go ahead and construct the user_setup_url
            if (result.Version.Major < 2 && request.Immediate && channel != null)
            {
                // All requests are CheckIdRequests in OpenID 1.x, so this cast should be safe.
                result.UserSetupUrl = await ConstructUserSetupUrlAsync((CheckIdRequest)request, channel, cancellationToken);
            }

            return(result);
        }
		public void ImmediateVsSetupModes() {
			this.responseMessage = new NegativeAssertionResponse(this.protocol.Version, RPUri, this.protocol.Args.Mode.cancel);
			this.response = new NegativeAuthenticationResponse(this.responseMessage);
			Assert.AreEqual(AuthenticationStatus.Canceled, this.response.Status);
			try {
				Assert.AreEqual(UserSuppliedIdentifier, this.response.UserSuppliedIdentifier);
				Assert.Fail("Expected InvalidOperationException not thrown.");
			} catch (InvalidOperationException) {
			}

			this.responseMessage = new NegativeAssertionResponse(this.protocol.Version, RPUri, this.protocol.Args.Mode.setup_needed);
			this.responseMessage.ExtraData[AuthenticationRequest.UserSuppliedIdentifierParameterName] = UserSuppliedIdentifier;
			this.response = new NegativeAuthenticationResponse(this.responseMessage);
			Assert.AreEqual(AuthenticationStatus.SetupRequired, this.response.Status);
			Assert.AreEqual(UserSuppliedIdentifier, (string)this.response.UserSuppliedIdentifier);
		}
        /// <summary>
        /// Initializes a new instance of the <see cref="AuthenticationRequest"/> class.
        /// </summary>
        /// <param name="provider">The provider that received the request.</param>
        /// <param name="request">The incoming authentication request message.</param>
        internal AuthenticationRequest(OpenIdProvider provider, CheckIdRequest request)
            : base(request)
        {
            ErrorUtilities.VerifyArgumentNotNull(provider, "provider");

            this.positiveResponse = new PositiveAssertionResponse(request);
            this.negativeResponse = new NegativeAssertionResponse(request, provider.Channel);

            if (this.ClaimedIdentifier == Protocol.ClaimedIdentifierForOPIdentifier &&
                Protocol.ClaimedIdentifierForOPIdentifier != null) {
                // Force the hosting OP to deal with identifier_select by nulling out the two identifiers.
                this.IsDirectedIdentity = true;
                this.positiveResponse.ClaimedIdentifier = null;
                this.positiveResponse.LocalIdentifier = null;
            }

            // URL delegation is only detectable from 2.0 RPs, since openid.claimed_id isn't included from 1.0 RPs.
            // If the openid.claimed_id is present, and if it's different than the openid.identity argument, then
            // the RP has discovered a claimed identifier that has delegated authentication to this Provider.
            this.IsDelegatedIdentifier = this.ClaimedIdentifier != null && this.ClaimedIdentifier != this.LocalIdentifier;
        }
		private void ParameterizedAuthenticationTest(Protocol protocol, bool statelessRP, bool sharedAssociation, bool positive, bool immediate, bool tamper) {
			Contract.Requires<ArgumentException>(!statelessRP || !sharedAssociation, "The RP cannot be stateless while sharing an association with the OP.");
			Contract.Requires<ArgumentException>(positive || !tamper, "Cannot tamper with a negative response.");
			var securitySettings = new ProviderSecuritySettings();
			var cryptoKeyStore = new MemoryCryptoKeyStore();
			var associationStore = new ProviderAssociationHandleEncoder(cryptoKeyStore);
			Association association = sharedAssociation ? HmacShaAssociation.Create(protocol, protocol.Args.SignatureAlgorithm.Best, AssociationRelyingPartyType.Smart, associationStore, securitySettings) : null;
			var coordinator = new OpenIdCoordinator(
				rp => {
					var request = new CheckIdRequest(protocol.Version, OPUri, immediate ? AuthenticationRequestMode.Immediate : AuthenticationRequestMode.Setup);

					if (association != null) {
						StoreAssociation(rp, OPUri, association);
						request.AssociationHandle = association.Handle;
					}

					request.ClaimedIdentifier = "http://claimedid";
					request.LocalIdentifier = "http://localid";
					request.ReturnTo = RPUri;
					request.Realm = RPUri;
					rp.Channel.Respond(request);
					if (positive) {
						if (tamper) {
							try {
								rp.Channel.ReadFromRequest<PositiveAssertionResponse>();
								Assert.Fail("Expected exception {0} not thrown.", typeof(InvalidSignatureException).Name);
							} catch (InvalidSignatureException) {
								TestLogger.InfoFormat("Caught expected {0} exception after tampering with signed data.", typeof(InvalidSignatureException).Name);
							}
						} else {
							var response = rp.Channel.ReadFromRequest<PositiveAssertionResponse>();
							Assert.IsNotNull(response);
							Assert.AreEqual(request.ClaimedIdentifier, response.ClaimedIdentifier);
							Assert.AreEqual(request.LocalIdentifier, response.LocalIdentifier);
							Assert.AreEqual(request.ReturnTo, response.ReturnTo);

							// Attempt to replay the message and verify that it fails.
							// Because in various scenarios and protocol versions different components
							// notice the replay, we can get one of two exceptions thrown.
							// When the OP notices the replay we get a generic InvalidSignatureException.
							// When the RP notices the replay we get a specific ReplayMessageException.
							try {
								CoordinatingChannel channel = (CoordinatingChannel)rp.Channel;
								channel.Replay(response);
								Assert.Fail("Expected ProtocolException was not thrown.");
							} catch (ProtocolException ex) {
								Assert.IsTrue(ex is ReplayedMessageException || ex is InvalidSignatureException, "A {0} exception was thrown instead of the expected {1} or {2}.", ex.GetType(), typeof(ReplayedMessageException).Name, typeof(InvalidSignatureException).Name);
							}
						}
					} else {
						var response = rp.Channel.ReadFromRequest<NegativeAssertionResponse>();
						Assert.IsNotNull(response);
						if (immediate) {
							// Only 1.1 was required to include user_setup_url
							if (protocol.Version.Major < 2) {
								Assert.IsNotNull(response.UserSetupUrl);
							}
						} else {
							Assert.IsNull(response.UserSetupUrl);
						}
					}
				},
				op => {
					if (association != null) {
						var key = cryptoKeyStore.GetCurrentKey(ProviderAssociationHandleEncoder.AssociationHandleEncodingSecretBucket, TimeSpan.FromSeconds(1));
						op.CryptoKeyStore.StoreKey(ProviderAssociationHandleEncoder.AssociationHandleEncodingSecretBucket, key.Key, key.Value);
					}

					var request = op.Channel.ReadFromRequest<CheckIdRequest>();
					Assert.IsNotNull(request);
					IProtocolMessage response;
					if (positive) {
						response = new PositiveAssertionResponse(request);
					} else {
						response = new NegativeAssertionResponse(request, op.Channel);
					}
					op.Channel.Respond(response);

					if (positive && (statelessRP || !sharedAssociation)) {
						var checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>();
						var checkauthResponse = new CheckAuthenticationResponse(checkauthRequest.Version, checkauthRequest);
						checkauthResponse.IsValid = checkauthRequest.IsValid;
						op.Channel.Respond(checkauthResponse);

						if (!tamper) {
							// Respond to the replay attack.
							checkauthRequest = op.Channel.ReadFromRequest<CheckAuthenticationRequest>();
							checkauthResponse = new CheckAuthenticationResponse(checkauthRequest.Version, checkauthRequest);
							checkauthResponse.IsValid = checkauthRequest.IsValid;
							op.Channel.Respond(checkauthResponse);
						}
					}
				});
			if (tamper) {
				coordinator.IncomingMessageFilter = message => {
					var assertion = message as PositiveAssertionResponse;
					if (assertion != null) {
						// Alter the Local Identifier between the Provider and the Relying Party.
						// If the signature binding element does its job, this should cause the RP
						// to throw.
						assertion.LocalIdentifier = "http://victim";
					}
				};
			}
			if (statelessRP) {
				coordinator.RelyingParty = new OpenIdRelyingParty(null);
			}

			coordinator.Run();
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="NegativeAssertionResponse" /> class.
		/// </summary>
		/// <param name="request">The request that the relying party sent.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <param name="channel">The channel to use to simulate construction of the user_setup_url, if applicable.  May be null, but the user_setup_url will not be constructed.</param>
		/// <returns>The negative assertion message that will indicate failure for the user to authenticate or an unwillingness to log into the relying party.</returns>
		internal static async Task<NegativeAssertionResponse> CreateAsync(SignedResponseRequest request, CancellationToken cancellationToken, Channel channel = null) {
			var result = new NegativeAssertionResponse(request);

			// If appropriate, and when we're provided with a channel to do it,
			// go ahead and construct the user_setup_url
			if (result.Version.Major < 2 && request.Immediate && channel != null) {
				// All requests are CheckIdRequests in OpenID 1.x, so this cast should be safe.
				result.UserSetupUrl = await ConstructUserSetupUrlAsync((CheckIdRequest)request, channel, cancellationToken);
			}

			return result;
		}