Example #1
0
        private static async Task HandleTokenRefreshFailure(HttpResponseMessage response)
        {
            // OneDrive specific logic: If the refresh token is expired, the server will return a 400 Bad Request
            // response with json content saying that the user must sign in.
            if (response.StatusCode == HttpStatusCode.BadRequest)
            {
                WindowsLiveError errorData = await response.Content.TryReadAsJsonAsync <WindowsLiveError>().ConfigureAwait(false);

                if (errorData != null && errorData.Error == "invalid_grant")
                {
                    throw new OneDriveTokenRefreshFailedException("The refresh token is expired.", errorData);
                }
            }

            // Dev note: Try to understand all of the refresh token failures. Any expected failures should be
            // throw as OneDriveTokenRefreshFailedException. This is here as a catch-all.
            var exception = new OneDriveHttpException("Failed to refresh token.", response.StatusCode);

            if (response.Headers.Contains("WwwAuthenticate"))
            {
                exception.Data["HttpAuthenticationHeader"] = response.Headers.WwwAuthenticate;
            }

            throw exception;
        }
Example #2
0
        private async Task <HttpResponseMessage> SendOneDriveRequest(HttpRequestMessage request)
        {
            var response = await this.SendOneDriveRequest(request, this.oneDriveHttpClient).ConfigureAwait(false);

            // Any failures (including those from re-issuing after a refresh) will ne handled here
            if (!response.IsSuccessStatusCode)
            {
                throw OneDriveHttpException.FromResponse(response);
            }

            return(response);
        }
Example #3
0
        public static Exception FromResponse(HttpResponseMessage response)
        {
            string exceptionMessage = string.Format("The OneDrive service returned {0} ({1})", (int)response.StatusCode,
                                                    response.ReasonPhrase);

            OneDriveErrorResponseContainer errorResponse = response.Content.TryReadAsJsonAsync <OneDriveErrorResponseContainer>().Result;

            var exception = new OneDriveHttpException(exceptionMessage, response.StatusCode);

            if (errorResponse != null)
            {
                exception.ErrorResponse = errorResponse.ErrorResponse;
            }

            foreach (KeyValuePair <string, IEnumerable <string> > responseHeader in response.Headers)
            {
                exception.ResponseHeaders.Add(responseHeader.Key, new List <string>(responseHeader.Value));
            }

            return(exception);
        }
Example #4
0
        /// <summary>
        /// Send an HTTP request to the Live endpoint, handling the case when a token refresh is required.
        /// </summary>
        /// <remarks>
        /// The caller must provide the request to send. The authentication header will be set by this method. Any error
        /// returned by the call (including failure to refresh the token) will result in an exception being thrown.
        /// </remarks>
        private async Task <HttpResponseMessage> SendLiveRequest(HttpRequestMessage request)
        {
            var qsParams = request.RequestUri.GetQueryParameters();

            qsParams["access_token"] = this.CurrentToken.AccessToken;

            var uriParts = request.RequestUri.ToString().Split(new [] { '?' }, 2);

            request.RequestUri = new Uri(uriParts[0] + UriExtensions.CombineQueryString(qsParams));

            LogRequest(request, this.liveHttpClient.BaseAddress);
            HttpResponseMessage response = await this.liveHttpClient.SendAsync(request).ConfigureAwait(false);

            LogResponse(response);

            // Check for token refresh
            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                string responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                bool refreshToken = false;

                try
                {
                    JObject jObject = JObject.Parse(responseContent);
                    refreshToken = Convert.ToString(jObject["error"]["code"]) == "request_token_expired";
                }
                catch
                {
                    // There was an error parsing the response from the server.
                }

                if (refreshToken)
                {
                    // Refresh the current token
                    await this.RefreshToken().ConfigureAwait(false);

                    var newRequest = await request.Clone().ConfigureAwait(false);

                    // Resend the request using the new token
                    qsParams = newRequest.RequestUri.GetQueryParameters();
                    qsParams["access_token"] = this.CurrentToken.AccessToken;

                    uriParts = newRequest.RequestUri.ToString().Split(new[] { '?' }, 2);
                    newRequest.RequestUri = new Uri(uriParts[0] + UriExtensions.CombineQueryString(qsParams));
                    LogRequest(request, this.liveHttpClient.BaseAddress);
                    response = await this.liveHttpClient.SendAsync(newRequest).ConfigureAwait(false);

                    LogResponse(response);
                }
            }

            // Any failures (including those from re-issuing after a refresh) will be handled here
            if (!response.IsSuccessStatusCode)
            {
                var exception = new OneDriveHttpException("Live exception", response.StatusCode);
                exception.Data["Content"] = response.Content.ReadAsStringAsync().Result;
                throw exception;
            }

            return(response);
        }