/// <summary> /// Searches for a bearer access token in the request. /// </summary> /// <param name="request">The request.</param> /// <returns>The bearer access token, if one exists. Otherwise <c>null</c>.</returns> private static string SearchForBearerAccessTokenInRequest(HttpRequestBase request) { Requires.NotNull(request, "request"); // First search the authorization header. string authorizationHeader = request.Headers[HttpRequestHeaders.Authorization]; if (!string.IsNullOrEmpty(authorizationHeader) && authorizationHeader.StartsWith(Protocol.BearerHttpAuthorizationSchemeWithTrailingSpace, StringComparison.OrdinalIgnoreCase)) { return(authorizationHeader.Substring(Protocol.BearerHttpAuthorizationSchemeWithTrailingSpace.Length)); } // Failing that, scan 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)) { if (request.Form[Protocol.BearerTokenEncodedUrlParameterName] != null) { return(request.Form[Protocol.BearerTokenEncodedUrlParameterName]); } } } // Finally, check the least desirable location: the query string var unrewrittenQuery = request.GetQueryStringBeforeRewriting(); if (!string.IsNullOrEmpty(unrewrittenQuery[Protocol.BearerTokenEncodedUrlParameterName])) { return(unrewrittenQuery[Protocol.BearerTokenEncodedUrlParameterName]); } return(null); }
/// <summary> /// Generates the authentication requests that can satisfy the requirements of some OpenID Identifier. /// </summary> /// <param name="userSuppliedIdentifier">The Identifier supplied by the user. This may be a URL, an XRI or i-name.</param> /// <param name="realm">The shorest URL that describes this relying party web site's address. /// For example, if your login page is found at https://www.example.com/login.aspx, /// your realm would typically be https://www.example.com/.</param> /// <param name="requestContext">The request context.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns> /// A sequence of authentication requests, any of which constitutes a valid identity assertion on the Claimed Identifier. /// Never null, but may be empty. /// </returns> /// <exception cref="InvalidOperationException">Thrown if <see cref="HttpContext.Current">HttpContext.Current</see> == <c>null</c>.</exception> /// <remarks> /// <para>Any individual generated request can satisfy the authentication. /// The generated requests are sorted in preferred order. /// Each request is generated as it is enumerated to. Associations are created only as /// <see cref="IAuthenticationRequest.GetRedirectingResponseAsync" /> is called.</para> /// <para>No exception is thrown if no OpenID endpoints were discovered. /// An empty enumerable is returned instead.</para> /// <para>Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.</para> /// </remarks> public async Task <IEnumerable <IAuthenticationRequest> > CreateRequestsAsync(Identifier userSuppliedIdentifier, Realm realm, HttpRequestBase requestContext = null, CancellationToken cancellationToken = default(CancellationToken)) { RequiresEx.ValidState(requestContext != null || (HttpContext.Current != null && HttpContext.Current.Request != null), MessagingStrings.HttpContextRequired); Requires.NotNull(userSuppliedIdentifier, "userSuppliedIdentifier"); Requires.NotNull(realm, "realm"); requestContext = requestContext ?? this.channel.GetRequestFromContext(); // This next code contract is a BAD idea, because it causes each authentication request to be generated // at least an extra time. //// // Build the return_to URL UriBuilder returnTo = new UriBuilder(requestContext.GetPublicFacingUrl()); // Trim off any parameters with an "openid." prefix, and a few known others // to avoid carrying state from a prior login attempt. returnTo.Query = string.Empty; NameValueCollection queryParams = requestContext.GetQueryStringBeforeRewriting(); var returnToParams = new Dictionary <string, string>(queryParams.Count); foreach (string key in queryParams) { if (!IsOpenIdSupportingParameter(key) && key != null) { returnToParams.Add(key, queryParams[key]); } } returnTo.AppendQueryArgs(returnToParams); return(await this.CreateRequestsAsync(userSuppliedIdentifier, realm, returnTo.Uri, cancellationToken)); }
/// <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) { 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) { 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); }