/// <summary>
		/// Gets the protocol message that may be embedded in the given HTTP request.
		/// </summary>
		/// <param name="request">The request to search for an embedded message.</param>
		/// <returns>
		/// The deserialized message, if one is found.  Null otherwise.
		/// </returns>
		protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) {
			Logger.Channel.DebugFormat("Incoming HTTP request: {0} {1}", request.HttpMethod, request.GetPublicFacingUrl().AbsoluteUri);

			var fields = request.GetQueryStringBeforeRewriting().ToDictionary();

			// Also read parameters from the fragment, if it's available.
			// Typically the fragment is not available because the browser doesn't send it to a web server
			// but this request may have been fabricated by an installed desktop app, in which case
			// the fragment is available.
			string fragment = request.GetPublicFacingUrl().Fragment;
			if (!string.IsNullOrEmpty(fragment)) {
				foreach (var pair in HttpUtility.ParseQueryString(fragment.Substring(1)).ToDictionary()) {
					fields.Add(pair.Key, pair.Value);
				}
			}

			MessageReceivingEndpoint recipient;
			try {
				recipient = request.GetRecipient();
			} catch (ArgumentException ex) {
				Logger.Messaging.WarnFormat("Unrecognized HTTP request: ", ex);
				return null;
			}

			return (IDirectedProtocolMessage)this.Receive(fields, recipient);
		}
Beispiel #2
0
		/// <summary>
		/// Searches an incoming HTTP request for data that could be used to assemble
		/// a protocol request message.
		/// </summary>
		/// <param name="request">The HTTP request to search.</param>
		/// <returns>The deserialized message, if one is found.  Null otherwise.</returns>
		protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) {
			// First search the Authorization header.
			string authorization = request.Headers[HttpRequestHeaders.Authorization];
			var fields = MessagingUtilities.ParseAuthorizationHeader(Protocol.AuthorizationHeaderScheme, authorization).ToDictionary();
			fields.Remove("realm"); // ignore the realm parameter, since we don't use it, and it must be omitted from signature base string.

			// Scrape the entity
			if (!string.IsNullOrEmpty(request.Headers[HttpRequestHeaders.ContentType])) {
				var contentType = new ContentType(request.Headers[HttpRequestHeaders.ContentType]);
				if (string.Equals(contentType.MediaType, HttpFormUrlEncoded, StringComparison.Ordinal)) {
					foreach (string key in request.Form) {
						if (key != null) {
							fields.Add(key, request.Form[key]);
						} else {
							Logger.OAuth.WarnFormat("Ignoring query string parameter '{0}' since it isn't a standard name=value parameter.", request.Form[key]);
						}
					}
				}
			}

			// Scrape the query string
			var qs = request.GetQueryStringBeforeRewriting();
			foreach (string key in qs) {
				if (key != null) {
					fields.Add(key, qs[key]);
				} else {
					Logger.OAuth.WarnFormat("Ignoring query string parameter '{0}' since it isn't a standard name=value parameter.", qs[key]);
				}
			}

			MessageReceivingEndpoint recipient;
			try {
				recipient = request.GetRecipient();
			} catch (ArgumentException ex) {
				Logger.OAuth.WarnFormat("Unrecognized HTTP request: " + ex.ToString());
				return null;
			}

			// Deserialize the message using all the data we've collected.
			var message = (IDirectedProtocolMessage)this.Receive(fields, recipient);

			// Add receiving HTTP transport information required for signature generation.
			var signedMessage = message as ITamperResistantOAuthMessage;
			if (signedMessage != null) {
				signedMessage.Recipient = request.GetPublicFacingUrl();
				signedMessage.HttpMethod = request.HttpMethod;
			}

			return message;
		}
Beispiel #3
0
		/// <summary>
		/// Records statistics collected from incoming requests.
		/// </summary>
		/// <param name="request">The request.</param>
		internal static void RecordRequestStatistics(HttpRequestBase request) {
			Contract.Requires(request != null);

			// In release builds, just quietly return.
			if (request == null) {
				return;
			}

			if (Enabled) {
				if (Configuration.IncludeCultures) {
					observedCultures.Add(Thread.CurrentThread.CurrentCulture.Name);
				}

				if (Configuration.IncludeLocalRequestUris && !observedRequests.IsFull) {
					var requestBuilder = new UriBuilder(request.GetPublicFacingUrl());
					requestBuilder.Query = null;
					requestBuilder.Fragment = null;
					observedRequests.Add(requestBuilder.Uri.AbsoluteUri);
				}

				Touch();
			}
		}
		/// <summary>
		/// Processes the authorization response from an authorization server, if available.
		/// </summary>
		/// <param name="request">The incoming HTTP request that may carry an authorization response.</param>
		/// <returns>The authorization state that contains the details of the authorization.</returns>
		public IAuthorizationState ProcessUserAuthorization(HttpRequestBase request = null) {
			Requires.ValidState(!string.IsNullOrEmpty(this.ClientIdentifier), OAuth2Strings.RequiredPropertyNotYetPreset, "ClientIdentifier");
			Requires.ValidState(!string.IsNullOrEmpty(this.ClientSecret), OAuth2Strings.RequiredPropertyNotYetPreset, "ClientSecret");

			if (request == null) {
				request = this.Channel.GetRequestFromContext();
			}

			IMessageWithClientState response;
			if (this.Channel.TryReadFromRequest<IMessageWithClientState>(request, out response)) {
				Uri callback = MessagingUtilities.StripMessagePartsFromQueryString(request.GetPublicFacingUrl(), this.Channel.MessageDescriptions.Get(response));
				IAuthorizationState authorizationState;
				if (this.AuthorizationTracker != null) {
					authorizationState = this.AuthorizationTracker.GetAuthorizationState(callback, response.ClientState);
					ErrorUtilities.VerifyProtocol(authorizationState != null, OAuth2Strings.AuthorizationResponseUnexpectedMismatch);
				} else {
					var context = this.Channel.GetHttpContext();
					if (context.Session != null) {
						ErrorUtilities.VerifyProtocol(string.Equals(response.ClientState, context.Session.SessionID, StringComparison.Ordinal), OAuth2Strings.AuthorizationResponseUnexpectedMismatch);
					} else {
						Logger.OAuth.WarnFormat("No request context discovered, so no client state parameter could be checked to mitigate XSRF attacks.");
					}

					authorizationState = new AuthorizationState { Callback = callback };
				}
				var success = response as EndUserAuthorizationSuccessAuthCodeResponse;
				var failure = response as EndUserAuthorizationFailedResponse;
				ErrorUtilities.VerifyProtocol(success != null || failure != null, MessagingStrings.UnexpectedMessageReceivedOfMany);
				if (success != null) {
					this.UpdateAuthorizationWithResponse(authorizationState, success);
				} else { // failure
					Logger.OAuth.Info("User refused to grant the requested authorization at the Authorization Server.");
					authorizationState.Delete();
				}

				return authorizationState;
			}

			return null;
		}
		/// <summary>
		/// Gets the incoming OpenID request if there is one, or null if none was detected.
		/// </summary>
		/// <param name="httpRequestInfo">The incoming HTTP request to extract the message from.</param>
		/// <returns>
		/// The request that the hosting Provider should process and then transmit the response for.
		/// Null if no valid OpenID request was detected in the given HTTP request.
		/// </returns>
		/// <remarks>
		/// Requests may be infrastructural to OpenID and allow auto-responses, or they may
		/// be authentication requests where the Provider site has to make decisions based
		/// on its own user database and policies.
		/// </remarks>
		/// <exception cref="ProtocolException">Thrown if the incoming message is recognized
		/// but deviates from the protocol specification irrecoverably.</exception>
		public IRequest GetRequest(HttpRequestBase httpRequestInfo) {
			Requires.NotNull(httpRequestInfo, "httpRequestInfo");
			IDirectedProtocolMessage incomingMessage = null;

			try {
				incomingMessage = this.Channel.ReadFromRequest(httpRequestInfo);
				if (incomingMessage == null) {
					// If the incoming request does not resemble an OpenID message at all,
					// it's probably a user who just navigated to this URL, and we should
					// just return null so the host can display a message to the user.
					if (httpRequestInfo.HttpMethod == "GET" && !httpRequestInfo.GetPublicFacingUrl().QueryStringContainPrefixedParameters(Protocol.Default.openid.Prefix)) {
						return null;
					}

					ErrorUtilities.ThrowProtocol(MessagingStrings.UnexpectedMessageReceivedOfMany);
				}

				IRequest result = null;

				var checkIdMessage = incomingMessage as CheckIdRequest;
				if (checkIdMessage != null) {
					result = new AuthenticationRequest(this, checkIdMessage);
				}

				if (result == null) {
					var extensionOnlyRequest = incomingMessage as SignedResponseRequest;
					if (extensionOnlyRequest != null) {
						result = new AnonymousRequest(this, extensionOnlyRequest);
					}
				}

				if (result == null) {
					var checkAuthMessage = incomingMessage as CheckAuthenticationRequest;
					if (checkAuthMessage != null) {
						result = new AutoResponsiveRequest(incomingMessage, new CheckAuthenticationResponseProvider(checkAuthMessage, this), this.SecuritySettings);
					}
				}

				if (result == null) {
					var associateMessage = incomingMessage as IAssociateRequestProvider;
					if (associateMessage != null) {
						result = new AutoResponsiveRequest(incomingMessage, AssociateRequestProviderTools.CreateResponse(associateMessage, this.AssociationStore, this.SecuritySettings), this.SecuritySettings);
					}
				}

				if (result != null) {
					foreach (var behavior in this.Behaviors) {
						if (behavior.OnIncomingRequest(result)) {
							// This behavior matched this request.
							break;
						}
					}

					return result;
				}

				throw ErrorUtilities.ThrowProtocol(MessagingStrings.UnexpectedMessageReceivedOfMany);
			} catch (ProtocolException ex) {
				IRequest errorResponse = this.GetErrorResponse(ex, httpRequestInfo, incomingMessage);
				if (errorResponse == null) {
					throw;
				}

				return errorResponse;
			}
		}
		/// <summary>
		/// Processes the authorization response from an authorization server, if available.
		/// </summary>
		/// <param name="request">The incoming HTTP request that may carry an authorization response.</param>
		/// <returns>The authorization state that contains the details of the authorization.</returns>
		public IAuthorizationState ProcessUserAuthorization(HttpRequestBase request = null) {
			RequiresEx.ValidState(!string.IsNullOrEmpty(this.ClientIdentifier), Strings.RequiredPropertyNotYetPreset, "ClientIdentifier");
			RequiresEx.ValidState(this.ClientCredentialApplicator != null, Strings.RequiredPropertyNotYetPreset, "ClientCredentialApplicator");

			if (request == null) {
				request = this.Channel.GetRequestFromContext();
			}

			IMessageWithClientState response;
			if (this.Channel.TryReadFromRequest<IMessageWithClientState>(request, out response)) {
				Uri callback = MessagingUtilities.StripMessagePartsFromQueryString(request.GetPublicFacingUrl(), this.Channel.MessageDescriptions.Get(response));
				IAuthorizationState authorizationState;
				if (this.AuthorizationTracker != null) {
					authorizationState = this.AuthorizationTracker.GetAuthorizationState(callback, response.ClientState);
					ErrorUtilities.VerifyProtocol(authorizationState != null, ClientStrings.AuthorizationResponseUnexpectedMismatch);
				} else {
					var context = this.Channel.GetHttpContext();

					HttpCookie cookie = request.Cookies[XsrfCookieName];
					ErrorUtilities.VerifyProtocol(cookie != null && string.Equals(response.ClientState, cookie.Value, StringComparison.Ordinal), ClientStrings.AuthorizationResponseUnexpectedMismatch);
					authorizationState = new AuthorizationState { Callback = callback };
				}
				var success = response as EndUserAuthorizationSuccessAuthCodeResponse;
				var failure = response as EndUserAuthorizationFailedResponse;
				ErrorUtilities.VerifyProtocol(success != null || failure != null, MessagingStrings.UnexpectedMessageReceivedOfMany);
				if (success != null) {
					this.UpdateAuthorizationWithResponse(authorizationState, success);
				} else { // failure
					Logger.OAuth.Info("User refused to grant the requested authorization at the Authorization Server.");
					authorizationState.Delete();
				}

				return authorizationState;
			}

			return null;
		}