cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Announcements
Want to learn some quick and useful tips to make your day easier? Check out how Calvin uses Replay to get feedback from other teams at Dropbox here.

Dropbox API Support & Feedback

Find help with the Dropbox API from other developers.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Re: Can't get PKCE access token uses javascript fetch request

Can't get PKCE access token uses javascript fetch request

ancso
Helpful | Level 6
Go to solution

I am trying to utilize the PKCE in a background script of chrome extension
example shows the following:

 

curl https://api.dropbox.com/oauth2/token \
 -d code=<AUTHORIZATION_CODE> \
 -d grant_type=authorization_code \
 -d code_verifier=<CODE_VERIFIER> \
 -d client_id=<APP_KEY>

 

my code:

 

 var dbxParams = new URLSearchParams({
    client_id:      client_id,
    grant_type:     "authorization_code",
    code:           access_code,
    code_verifier:  code_verifier,
  });
   var url = "https://api.dropbox.com/oauth2/token";

  fetch(url, {
    method: 'POST',
    body: dbxParams
  })
  .then(function(response){
    return response.json()
  })
  .then(function (data) {
    console.log('Request succeeded with JSON response', data);
  })
  .catch(function (error) {
    console.log('Request failed', error);
  });

 

i always get the same reply:

 

{"error_description": "No auth function available for given request", "error": "invalid_request"}
​

 

can you help?

 

1 Accepted Solution

Accepted Solutions

ancso
Helpful | Level 6
Go to solution

yes!
that was the problem
my apologies I missed these arguments in the request URL

 

however,
i am now getting the error 

 

{error: 'invalid_grant', error_description: 'invalid code verifier'}

 

 

The URL includes both code_challenge and code_challenge_method
and looks like:

 

https://www.dropbox.com/oauth2/authorize?response_type=code&client_id=<client_id>&code_challenge=<code_challenge>&code_challenge_method=S256

 


and the parameters sent to oauth2/token are:

 

client_id=<client_id>&grant_type=authorization_code&code=<auth code from dropbox>&code_verifier=<128 char verifier>

 

 

i also made sure that <code challenge> is a SHA256 hash of <128 char verifier> by testing it at https://emn178.github.io/online-tools/sha256.html

what am i missing?

View solution in original post

18 Replies 18

Здравко
Legendary | Level 20
Go to solution

Hi @ancso,

Where is 'redirect_uri' header in your call? 🤔 Did you forget it? 🧐 Review here again.

Good luck.

Greg-DB
Dropbox Staff
Go to solution

@ancso Is this the exact code you're running? I just gave it a try and it works for me when I plug in my own client_id, access_code, and code_verifier. (For reference, redirect_uri is optional in this flow, so that shouldn't be an issue.)

 

The "No auth function available for given request" error should indicate that the necessary authorization information, such as "code", etc., weren't provided (or weren't provided in a correct format that the Dropbox API servers understood). Can you check the network request, using the developer tools, to see what is/isn't being sent?

ancso
Helpful | Level 6
Go to solution

according to the de tools all parameters are sent
could it be that one of them is simply of wrong type?
if so I suppose it will be the calculation of the code_verifier
for such a small task i did not want to import a library so i have the following code:

var code_verifier = '';
var codeChallenge = '';  

  /**
   *
   */
  setDropboxCodes(){
    
    var codes = {};
    const base64Encode = (str) => {
      return str.toString('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
      }

    codeVerifier  = base64Encode(getRandomString(128));
    var code256 = _self.sha256(codes['codeVerifier'])
    .codeChallenge = base64Encode(code256);

  }

  /**
   *
   */
  getRandomString(length) {
    var randomChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var result = '';
    for ( var i = 0; i < length; i++ ) {
        result += randomChars.charAt(Math.floor(Math.random() * randomChars.length));
    }
    return result;
  }

 

Greg-DB
Dropbox Staff
Go to solution

Could you elaborate on what you mean when you say "according to the de tools all parameters are sent"? For instance, could you show the request (headers and body) that your client is sending? Be sure to redact any sensitive values themselves though.

 

If a parameter was being sent in the correct format but had an incorrect value, the API should respond with a different message than the one you're getting.

 

Also, it's worth mentioning that I'm not running this in the context of a Chrome extension, so that may be contributing to the difference.

ancso
Helpful | Level 6
Go to solution

since its SSL i am unable to use wireshrk/tcpdump
In the Chrome's dev tools, under the payload tab i can see the following (raw data):

 

 

client_id=<15 chars clienid>&grant_type=authorization_code&code=<43 chars code>&code_verifier=<128 chars code_verifier>

 

 

all codes include only lower&Upper case letters and numbers

i also tested this string at https://reqbin.com/req/v0crmky0/rest-api-post-example and got the same result

Greg-DB
Dropbox Staff
Go to solution

Could you show both the headers and body for both the request and response? The Chrome developer tools should enable you to see both.

ancso
Helpful | Level 6
Go to solution

the headers:
Untitled-1.png
because it is a chrome extension the body is not in it
there is a tab called payload instead:

Untitled-2.jpg

 

i tried to use the above string in  https://reqbin.com/req/v0crmky0/rest-api-post-example and got the same error
looks like the issue is not with the chrome extension, probably something to do with the data in the body

Thanks
Avner 

Greg-DB
Dropbox Staff
Go to solution

Thanks. In particular I was most looking for the "Content-Type" header which will affect how the body is read, but that seems to be set correctly in your screenshot. Were you also setting that to "application/x-www-form-urlencoded;charset=UTF-8" when using https://reqbin.com/req/v0crmky0/rest-api-post-example ? That could cause the error if not.

 

Also, I'm not sure why your request contains cookies; that's not expected for API calls like this. That doesn't occur for me, so I can't say if that's the cause. Perhaps it's because that one's happening in a Chrome extension (as opposed to the potential Content-Type issue in reqbin)?

 

In any case, perhaps you can share the actual unredacted payload? (The authorization code expires after five minutes, so it's safe to share once that elapses.) You can open an API ticket with that if you'd prefer to share privately. That may enable us to reproduce what you're seeing. Alternatively, do you have a sample page with this code running we can try?

ancso
Helpful | Level 6
Go to solution

when using the  https://reqbin.com/req/v0crmky0/rest-api-post-example i tried all types of content-type available with no luck
I don't believe the cookie should matter, usually API servers do not relate to any irrelevant information unless it is actually needed,
however,
would be good if you could check that with the programmers
as you said, this is chrome extension and I am unable to change this default behavior

the params I sent were:
client_id=<client_id>&grant_type=authorization_code&code=waO3hkmKk8EAAAAAAAAL04IbHdMrBYxBGw7yghMI_0o&code_verifier=HfW9Gz3ZtF3mgdZCq3wuIIzbPDmwaGbkrOgMLgYYv6GeYXvLAMusvBjrJ91Zv8bFKhTOHlHj3EyAqMz5tivKXSLQS1r5NpSeNLP61zz5JRh6MXAB0mAL7lTrzBuSlptc

let me know if you need anymore information

Need more support?