/// <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); }
/// <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; }
/// <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; }