codeignitercurloauth-2.0basecamp37-signals

Basecamp API authentication with OAuth2: internal checksum failed error


I'm trying to write a CodeIgniter controller to handle OAuth2 authentication for the 37signals' Basecamp API.

The problem is I keep encountering the 'internal checksum failed' error, when trying to connect (via cURL) to https://launchpad.37signals.com/authorization.json, providing the Auth Token in a HTTP header.

Here's the index and _authcode functions from my controller class:

<?php 

// constants:
// BC_REQUEST_URL = 'https://launchpad.37signals.com/authorization/new'
// BC_TOKEN_URL   = 'https://launchpad.37signals.com/authorization/token'

// ... 

public function index() {
    // if get data is set.
    if ($this->input->get()) {

        // if auth code is provided via GET, switch to _authcode method.
        if ( $code = $this->input->get('code') ) {
            return $this->_authcode($code);
        }

        // On error, kill yourself.
        if ( $error = $this->input->get('error') ) {
            die($error);
        }

    }

    // redirect to 37 signals to get an authcode
    header("Location: ".BC_REQUEST_URL."?type=web_server&client_id=".BC_CLIENT_ID."&redirect_uri=".BC_REDIRECT_URL."");
}

// handles the Authentication code that is returned by 37 Signals.
private function _authcode($code) {
    // set vars to POST
    $vars = array(
        'type' => 'web_server',
        'client_id' => BC_CLIENT_ID,
        'redirect_uri' => BC_REDIRECT_URL,
        'client_secret' => BC_CLIENT_SECRET,
        'code' => $code
    );

    // make a request for the access_token
    $url = BC_TOKEN_URL;
    $c = curl_init($url);
    curl_setopt($c, CURLOPT_POST, true);
    curl_setopt($c, CURLOPT_POSTFIELDS, http_build_query($vars));
    curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
    $response = json_decode(curl_exec($c));
    curl_close($c);
    unset($c,$url);

    // get the access vars from this request
    $expiry_seconds = $response->expires_in;    // default: 1209600 (14 days)
    $refresh_token  = $response->refresh_token; 
    $access_token   = $response->access_token;  
    unset($response);

    // make a separate request to get user info for current user.
    $url = "https://launchpad.37signals.com/authorization.json";
    $c = curl_init($url);

    curl_setopt($c, CURLOPT_HTTPHEADER, array(
        "Authorization: Bearer <$access_token>",
        "Content-Type: application/json; charset=utf-8",
        "User-Agent: MyApp (http://myapp.example.com)"
    ));
    curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
    $response = json_decode(curl_exec($c)); // reply from 37 signal auth
    curl_close($c);
    unset($c,$url);

    echo "response obj = " . print_r($response,1);
    /* prints: response obj = stdClass Object ( [error] => OAuth token could not be verified. The internal checksum failed, so the token data was somehow mangled or tampered with. ) */

    // get the user data from this request
    // $expires_at = $response->expires_at; // the timestamp for when this request expires
    // $identity   = $response->identity;   // the current user
    // $accounts   = $response->accounts;   // list of accounts we can access
    // unset($response);

    // store the response data to the database for easy recall.
    // $this->db->query("REPLACE INTO `sometable` SET `key1`='value', `key2`='value');

}
// ...
?>

Solution

  • I ran into this error when saving the auth token in the database with varchar(255). Basecamp's auth token has some checksum data which brings the token over 255 characters.

    You don't appear to be pulling it from a database in your example, so this might not affect you, however checking for Basecamp's token being cut off is what I would first look at.

    Optionally, remove the <> characters around your $access_token when setting the Bearer header.