public async Task <bool> RefreshAccessToken(string[] scopeList = null) { if (this.options.OAuth2RefreshToken == null || this.options.AppKey == null) { // Cannot refresh token if you do not have at a minimum refresh token and app key return(false); } var url = "https://api.dropbox.com/oauth2/token"; var parameters = new Dictionary <string, string> { { "refresh_token", this.options.OAuth2RefreshToken }, { "grant_type", "refresh_token" }, { "client_id", this.options.AppKey } }; if (!string.IsNullOrEmpty(this.options.AppSecret)) { parameters["client_secret"] = this.options.AppSecret; } if (scopeList != null) { parameters["scope"] = String.Join(" ", scopeList); } var bodyContent = new FormUrlEncodedContent(parameters); var response = await this.defaultHttpClient.PostAsync(url, bodyContent).ConfigureAwait(false); //if response is an invalid grant, we want to throw this exception rather than the one thrown in // response.EnsureSuccessStatusCode(); if (response.StatusCode == HttpStatusCode.Unauthorized) { var reason = await response.Content.ReadAsStringAsync().ConfigureAwait(false); if (reason == "invalid_grant") { throw AuthException.Decode(reason, () => new AuthException(GetRequestId(response))); } } response.EnsureSuccessStatusCode(); if (response.IsSuccessStatusCode) { var json = JObject.Parse(await response.Content.ReadAsStringAsync()); string accessToken = json["access_token"].ToString(); DateTime tokenExpiration = DateTime.Now.AddSeconds(json["expires_in"].ToObject <int>()); this.options.OAuth2AccessToken = accessToken; this.options.OAuth2AccessTokenExpiresAt = tokenExpiration; return(true); } return(false); }
/// <summary> /// Requests the JSON string. /// </summary> /// <param name="host">The host.</param> /// <param name="routeName">Name of the route.</param> /// <param name="auth">The auth type of the route.</param> /// <param name="routeStyle">The route style.</param> /// <param name="requestArg">The request argument.</param> /// <param name="body">The body to upload if <paramref name="routeStyle"/> /// is <see cref="RouteStyle.Upload"/>.</param> /// <returns>The asynchronous task with the result.</returns> private async Task <Result> RequestJsonString( string host, string routeName, string auth, RouteStyle routeStyle, string requestArg, Stream body = null) { var hostname = this.options.HostMap[host]; var uri = this.GetRouteUri(hostname, routeName); var request = new HttpRequestMessage(HttpMethod.Post, uri); if (auth == AuthType.User || auth == AuthType.Team) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", this.options.OAuth2AccessToken); } else if (auth == AuthType.App) { request.Headers.Authorization = new AuthenticationHeaderValue("Basic", this.options.OAuth2AccessToken); } else if (auth == AuthType.NoAuth) { } else { throw new ArgumentException("Invalid auth type", auth); } request.Headers.TryAddWithoutValidation("User-Agent", this.options.UserAgent); if (this.selectUser != null) { request.Headers.TryAddWithoutValidation("Dropbox-Api-Select-User", this.selectUser); } if (this.selectAdmin != null) { request.Headers.TryAddWithoutValidation("Dropbox-Api-Select-Admin", this.selectAdmin); } var completionOption = HttpCompletionOption.ResponseContentRead; switch (routeStyle) { case RouteStyle.Rpc: request.Content = new StringContent(requestArg, Encoding.UTF8, "application/json"); break; case RouteStyle.Download: request.Headers.Add(DropboxApiArgHeader, requestArg); // This is required to force libcurl remove default content type header. request.Content = new StringContent(""); request.Content.Headers.ContentType = null; completionOption = HttpCompletionOption.ResponseHeadersRead; break; case RouteStyle.Upload: request.Headers.Add(DropboxApiArgHeader, requestArg); if (body == null) { throw new ArgumentNullException("body"); } request.Content = new CustomStreamContent(body); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); break; default: throw new InvalidOperationException(string.Format( CultureInfo.InvariantCulture, "Unknown route style: {0}", routeStyle)); } var disposeResponse = true; var response = await this.getHttpClient(host).SendAsync(request, completionOption).ConfigureAwait(false); var requestId = GetRequestId(response); try { if ((int)response.StatusCode >= 500) { var text = await response.Content.ReadAsStringAsync(); text = this.CheckForError(text); throw new RetryException(requestId, (int)response.StatusCode, message: text, uri: uri); } else if (response.StatusCode == HttpStatusCode.BadRequest) { var text = await response.Content.ReadAsStringAsync(); text = this.CheckForError(text); throw new BadInputException(requestId, text, uri); } else if (response.StatusCode == HttpStatusCode.Unauthorized) { var reason = await response.Content.ReadAsStringAsync(); throw AuthException.Decode(reason, () => new AuthException(GetRequestId(response))); } else if ((int)response.StatusCode == 429) { var reason = await response.Content.ReadAsStringAsync(); throw RateLimitException.Decode(reason, () => new RateLimitException(GetRequestId(response))); } else if (response.StatusCode == HttpStatusCode.Forbidden) { var reason = await response.Content.ReadAsStringAsync(); throw AccessException.Decode(reason, () => new AccessException(GetRequestId(response))); } else if (response.StatusCode == HttpStatusCode.Conflict || response.StatusCode == HttpStatusCode.NotFound) { var reason = await response.Content.ReadAsStringAsync(); return(new Result { IsError = true, ObjectResult = reason, RequestId = GetRequestId(response) }); } else if ((int)response.StatusCode >= 200 && (int)response.StatusCode <= 299) { if (routeStyle == RouteStyle.Download) { disposeResponse = false; return(new Result { IsError = false, ObjectResult = response.Headers.GetValues(DropboxApiResultHeader).FirstOrDefault(), HttpResponse = response }); } else { return(new Result { IsError = false, ObjectResult = await response.Content.ReadAsStringAsync() }); } } else { var text = await response.Content.ReadAsStringAsync(); text = this.CheckForError(text); throw new HttpException(requestId, (int)response.StatusCode, text, uri); } } finally { if (disposeResponse) { response.Dispose(); } } }