We are aware of the issue with the badge emails resending to everyone, we apologise for the inconvenience - learn more here.

Forum Discussion

polarzero's avatar
polarzero
Helpful | Level 5
2 years ago

Requests always fail from deployed website, but work fine in localhost

I'm using the SDK for requests from my Next.js website. Everything works fine in localhost, but as soon as it is deployed on Vercel, I can only get 400 Errors for my requests to the API.

 

See the following code:

 

// Get the Dropbox API client
export const getDropboxApiClient = async () => {
  const refreshToken = process.env.NEXT_PUBLIC_DROPBOX_REFRESH_TOKEN;
  const appKey = process.env.NEXT_PUBLIC_DROPBOX_APP_KEY;
  const appSecret = process.env.NEXT_PUBLIC_DROPBOX_APP_SECRET;

  const dbx = new Dropbox({
    clientId: appKey,
    clientSecret: appSecret,
    refreshToken: refreshToken,
  });

  return dbx;
};

 

 

 

// Get the available space for the account
const getAvailableSpace = async () => {
    const dbx = await getDropboxApiClient();
    const available = await dbx.usersGetSpaceUsage();
    console.log(available);
};

 

 

This request works perfectly on localhost, and returns:

 

After I've deployed the App on Vercel, and added the environment variables the same way as usual (it works great with other SDKs), it doest work anymore.

 

All requests to the Dropbox API result in this:

 

Looking more closely into the network tab, I noticed that the request headers are different on localhost and deployed website. See the following, from localhost:

and on the website:

The request is exactly the same, except that it is missing the `authorization` field! Which explains the error message in the response:

Error in call to API function "users/get_space_usage": Must provide HTTP header "Authorization" or URL parameter "authorization".

 

I have no idea what I'm doing wrong here, or what I should do. Moreover, it seems that the initial request to Dropbox works fine, given the Vercel logs:

 

I hope someone will be familiar with this issue, and can provide me with some guidance. Here are some links to relevant parts of the code:

https://github.com/polar0/nilslepretre-photo-galley/blob/main/data/getDropboxApiClient.js

https://github.com/polar0/nilslepretre-photo-galley/blob/main/pages/admin/dashboard.js

 

Thanks!

 

 

  • Thank you for this additional guidance.

     

    I could not make it work at first, but found a solution. For anyone else, new to making this kind of API calls and relying too much on abstracted calls with the SDK (like me), the data needs to be encoded before being passed to the body.

     

    const data = {
        grant_type: 'refresh_token',
        refresh_token: refreshToken,
        client_id: clientId,
        client_secret: clientSecret,
    };
    
    const response = await fetch(`https://api.dropboxapi.com/oauth2/token`, {
      method: 'POST',
      headers: {
        'content-type': 'application/x-www-form-urlencoded',
      },
      // Note this: the data needs to be encoded first!
      body: new URLSearchParams(data),
    });
    
    console.log(await response.json());

     

    Thanks again for your concern and patience!

  • Greg-DB's avatar
    Greg-DB
    Icon for Dropbox Staff rankDropbox Staff

    I see you're supplying a refresh token, app key, and app secret to the Dropbox JavaScript SDK. In that case, the SDK should automatically use those to retrieve a new short-lived access token (the string that starts with "sl.") whenever needed, which it would then use to perform Dropbox API calls (such as usersGetSpaceUsage).

     

    As you pointed out, in the failing case it appears to be lacking an access token.

     

    In the last screenshot you provided, I see what appears to be the call to use the refresh token to get an access token (with the 'grant_type' and 'refresh_token' parameters), however it looks like it's being made to your app's "/admin/dashboard" path, instead of the Dropbox token endpoint "https://api.dropboxapi.com/oauth2/token" as is necessary to receive the access token from Dropbox.

     

    It's not clear why that is using the wrong URL though. It is technically possible to change the domain (relevant code here and here, meant for internal testing), but that should only change the domain and not the path. From the code you shared though, I don't see you changing that setting anyway. Is the code posted on GitHub exactly what is being run the failing case? Otherwise, is there anything on that environment that would be rewriting requests?

    • polarzero's avatar
      polarzero
      Helpful | Level 5

      Hi Greg. Thanks a lot for taking the time to help me.

       

      The code in the repository is the exact one being used for the deployment (with Vercel), and as you could see I'm using a minimal setup. The only other API requests I'm using are made through Google Drive and Auth0 endpoints.

       

      There is one thing I could think of, but I'm uncertain if it's relevant. Some pages are protected, and can only be accessed if the user is connected. And /admin/dashboard is one of them.

      Therefore, navigating to this page, while not being connected, redirects to the Auth0 authentification page AUTH0_ISSUER_BASE_URL. On successful login, the user is sent back to the page.

       

      However, I've just tried making that page public again. It does not solve the issue, though I'm getting a different error, similar to what you've seen on the Vercel screenshot:

       

      So it does make the issue a bit more specific. It looks like I should find out why these requests are not made to the Dropbox API url, though they are on localhost, and how to fix it.

      I will try tweaking that domain tomorrow in the morning, it's getting late already here. Maybe I can get it back to the original one, though I did not change it. And I'll try to completely remove other libraries to isolate the problem.

       

      Thanks again for your help! I'll keep you updated, if I were to find any lead!

    • polarzero's avatar
      polarzero
      Helpful | Level 5

      Hi Greg, I finally found a fix. I still have no idea why this request URL was changed, but most important was to get it working.

       

      I had to make a direct request to the API (with the precise URL) to get a temporary access token, then create the Dropbox instance with it. Thereafter, I can keep the same system for making requests, since the only mismatch in the URL was related to the refresh token request. Some pieces of code, in case someone runs into the same issue:

       

      export const getDropboxApiClient = async () => {
        // Get the refresh token, client ID and secret
        const refreshToken = process.env.NEXT_PUBLIC_DROPBOX_REFRESH_TOKEN;
        const clientId = process.env.NEXT_PUBLIC_DROPBOX_APP_KEY;
        const clientSecret = process.env.NEXT_PUBLIC_DROPBOX_APP_SECRET;
      
        // Make the call with a specific address
        const response = await fetch(
          `https://api.dropboxapi.com/oauth2/token?grant_type=refresh_token&refresh_token=${refreshToken}&client_id=${clientId}&client_secret=${clientSecret}`,
          {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: null,
          },
        );
        const data = await response.json();
      
        const token = data.access_token;
        // Create the instance with that access token
        const dbx = new Dropbox({ accessToken: token });
      
        return dbx;
      };

       

      And then I can make requests the same way as before:

      const dbx = await getDropboxApiClient();
      const availableSpace = await dbx.usersGetSpaceUsage();

       

      The only issue here is that my private keys (refresh token, app ID and secret) are visible in the Headers, when navigating to the request headers, in the Debugger. But I'm sure I'll find a quick fix to that.

       

      Thanks a lot for your help, I had given up already before you pointed me to the right direction.

      • Greg-DB's avatar
        Greg-DB
        Icon for Dropbox Staff rankDropbox Staff

        Thanks for following up, and for sharing your code. It does seem like something is rewriting those requests but unfortunately I can't say what that might be. In any case, I'm glad to hear you got this working.

         

        By the way, the /oauth2/token endpoint does accept these parameter either on the URL or in the body, so for example (using curl for illustration), instead of:

        curl -X POST "https://api.dropboxapi.com/oauth2/token?refresh_token=REFRESH_TOKEN&grant_type=refresh_token&client_id=APP_KEY&client_secret=APP_SECRET"

        you can do:

        curl -X POST "https://api.dropboxapi.com/oauth2/token" --data "refresh_token=REFRESH_TOKEN&grant_type=refresh_token&client_id=APP_KEY&client_secret=APP_SECRET"

         (The "content-type" would be "application/x-www-form-urlencoded".)

About Dropbox API Support & Feedback

Node avatar for Dropbox API Support & Feedback

Find help with the Dropbox API from other developers.

5,877 PostsLatest Activity: 9 hours ago
325 Following

If you need more help you can view your support options (expected response time for an email or ticket is 24 hours), or contact us on X or Facebook.

For more info on available support options for your Dropbox plan, see this article.

If you found the answer to your question in this Community thread, please 'like' the post to say thanks and to let us know it was useful!