Search code examples
javascriptuserscriptsquire-api

Exchange Quire authorization code for access token with GM_xmlhttpRequest


This may be a stupid question and I have tried to follow the instructions given from the quire-api-blog but I still have trouble obtaining a token from a Tampermonkey javascript userscript.

FYI syntax for GM_xmlhttpRequest is available on https://www.tampermonkey.net/documentation.php?ext=dhdg#GM_xmlhttpRequest

I am using the following code:

GM_xmlhttpRequest({
    method: "POST",
    url: "https://quire.io/oauth/token",
    data: JSON.stringify({
              grant_type: "authorization_code",
              code: "xxx",
              client_id: ":yyy",
              client_secret: "zzz"
          }),
    onload: function(r){
        console.log(r);
    }
});

This returns in the console the following object:

finalUrl: "https://quire.io/oauth/token"
​
readyState: 4
​
response: 
​
responseHeaders: "content-encoding: gzip\r\ncontent-type: text/plain; charset=utf-8\r\ndate: Sun, 13 Oct 2019 09:04:26 GMT\r\nserver: nginx/1.17.3\r\nset-cookie: DARTSESSID=7d20dcf1f0eae6ce0f69d9fe615e9ce5; Path=/; HttpOnly\r\nx-content-type-options: nosniff\r\nx-firefox-spdy: h2\r\nx-frame-options: SAMEORIGIN\r\nx-xss-protection: 1; mode=block\r\n"
​
responseText: 
​
responseXML: 
​
status: 400
​
statusText: "Bad Request"

Any idea what went wrong?

Thank in advance for your kind answer.

Rafaël


Solution

  • You need to be careful on the content-type of your request. Different XHR APIs use different defaults.

    The OAUTH2 Specification for the Access Token Request describes the Content-Type to be application/x-www-form-urlencoded.

    While GreaseMonkey is sending requests using JSON by default, which can be changed, by setting the Content-Type Header and encoding the data as a String using 'x-www-form-urlcoded'

    GM.xmlHttpRequest({
      method: "POST",
      url: "https://quire.io/oauth/token",
      data: "grant_type=authorization_code&code=xxx&client_id=yyy&client_secret=zzz",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded"
      },
    

    jquery.ajax() does this automatically setting the default Content-Type to application/x-www-form-urlencoded

    IMPORTANT SIDE NOTE: Your usage of $.ajax() indicates usage in the browser. If that's true then DON'T do it! Exposing your client_secret to an application running inside the browser will allow anyone to authenticate as your quire identity and access your project using the grant_type: client_authentication. As of now the Quire API requires you to run a dedicated server, from which you have to perform the Access Token Request, to avoid exposing the client_secret. If you're using jquery at server side, then that's OK.

    There is the open Issue#8 to also support a client side authorization_code flow without using the client_secret (suitable from a SPA or browser extension).