Ad

OAuth2 Implicit Vs Authorization Code Grant For Fitbit API

- 1 answer

THE ANSWER TO THIS QUESTION WAS IN THE FACT THAT I WAS USING AUTHORIZATION CODE GRANT FLOW ON THE CLIENT SIDE.. THIS SEEMS TO RESULT IN BLOCKING ERROR..

CHECK UNDERNEATH FOR FUNCTIONING AUTHENTICATION OAUTH2 IMPLICIT GRANT FOR FITBIT API..

I am performing OAuth2 authentication against the Fitbit API. This all using the Authorization Code Grant Flow. So first getting the auth code, being redirected to my application, then exchanging this for the access token and getting data with this token.

Starting off at the homePage on the "post_request.html" page, pushing the "fitbit" button, the user is redirected to the Authorization EndPoint of Fitbit. I am using Node.js to build a localserver to host the application and to be able to redirect without any problem..

On being redirected, I retrieve the authorization code and make an AJAX POST request to trade the authorization code for an access token. I then make this POST request but I get the following error..

{"errors":[{"errorType":"invalid_client","message":"Invalid authorization header format. The header was not recognized to be a valid header for any of known implementations or a client_id was not specified in case of a public client Received header = BasicdW5kZWZpbmVk. Visit https://dev.fitbit.com/docs/oauth2 for more information on the Fitbit Web API authorization process."}],"success":false}

I think there might be an error in me url encoding the client_id and client_secret. Or in me setting the headers. But I cannot spot it. Can anyone help me out?

My HTML file is the following..

<body>

    <button onclick="fitbitAuth()">Fitbit</button>

    <!-- action = route, method = method -->
    <form action="/" method="POST" id="form">
        <h3>Email Address:</h3>
        <input type="email">
        <br>
        <h3>Password:</h3>
        <input type="password">     
        <br>
        <br>
        <button type="submit">Send Request</button>   
    </form>

</body>
</html>

My script is the following, it consists of 3 functions.. - base64 encoding function - onclick function for starting the OAuth2 process - function that trades in auth code for access token

// run this script upon landing back on the page with the authorization code 
            // specify and/ or calculate parameters 
            var url_terug = window.location.search;
            var auth_code = url_terug.substr(6);
            var granttype = "authorization_code";
            var redirect_uri = "http://localhost:3000/fitbit";
            var client_id = "xxxxx";
            var client_secret = "xxxxxxxxxxxx";
            var stringto_encode = client_id + ":" + client_secret;
            var encoded_string = "";
            console.log("auth code = " + auth_code);

            function baseEncode(stringto_encode){

                encoded_string = btoa(stringto_encode);
                console.log(encoded_string);

            }

            function getTokenFitBit(){

                baseEncode();

                // execute a POST request with the right parameters 
                var request = new XMLHttpRequest();
                request.open('POST', "https://api.fitbit.com/oauth2/token?client_id=" + client_id + "&grant_type=" + granttype + "&redirect_uri=" + redirect_uri + "&code=" + auth_code);

                request.setRequestHeader('Authorization', 'Basic'+ encoded_string);
                request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

                // Setup our listener to process completed requests
                request.onload = function () {

                    // Process our return data
                    // status code between 200 and 300 indicates success
                    if (request.status >= 200 && request.status < 300) {

                        console.log('success!', request);
                        console.log(request.responseText);

                        // continue with API calls.. 


                    // you could set up a broader response handling if there is a use case for it
                    } else {

                        console.log('The current token request failed!');

                    }
                };

                request.send();                    

            }

            getTokenFitBit();




            // get the access token out of the JSON response 
            // execute a GET request on the API endpoint 
            // handle the data 

          // upon clicking fitbit button, starting off the oauth2 authentication 
          function fitbitAuth() {

                window.location.href = 'https://www.fitbit.com/oauth2/authorize?client_id=xxxxx&response_type=code&scope=activity&redirect_uri=http://localhost:3000/fitbit&prompt=consent';

            }
Ad

Answer

In the above example, you appear to have missing a separator between the "Basic" header and it's value in this line:

  request.setRequestHeader('Authorization', 'Basic'+ encoded_string);

Provided you are building a web based applications, you may want to look into using the 'Implicit' Flow, too: https://oauth.net/2/grant-types/implicit/

Ad
source: stackoverflow.com
Ad