1

I am trying to build Drupal 7 RESTFul services that use OAuth Authentication/Authorization (I am aware of the difference), I am also trying to use RESTFul services from other sources. The idea is that everyone had to sign in only in to the Drupal site and will be able to use all functionallity.

So the Drupal site will be the provided of OAuth Authorization. I have a long way to go but I have build two and three legged OAuth request using OAuth-PHP. I wrote down what I did so far (The Code Works, in case you where wondering;-)) and at the end I have two questions.

No need to read it all if you know OAuth and the Drupal modules concernt with it you can just skip to the questions, thought it would be nice for people to see an working example

Preface

All the code and info is copied from forum post and webpages, I did almost nothing myself this is just an overview of what I found after googleing for 8 hours. Since I could not find a simple all covering overview, I made this. Hope it helps you all.

Provider

Install in Drupal to following modules:

  • Chaos Tools (CTools)
  • Services
  • OAuth
  • OAuth Login Provider

and enable:

  • REST Server
  • OAuth Authentication
  • Services
  • OAuth Provider UI
  • OAuth Login Provider
  • OAuth
  • Chaos tools

This should basically be all to get your Oauth provider working.

The important URL’s are the following:

'server_uri' => 'http://localhost/oauthlogin/api',
'request_token_uri' => 'http://localhost/oauth/request_token',
'authorize_uri' => 'http://localhost/oauth/authorize',
'access_token_uri' => 'http://localhost/oauth/access_token'

Client

To test your current OAuth 1 provider you can use various ways, here I will show examples of what you need to do to get an Drupal and a OAuth-PHP (http://code.google.com/p/oauth-php) example running.

Create a Consumer

A consumer is the site/application that will be using the Services offered by the OAuth Provider. Every consumer needs its own Key and Secret. To get this go to your Drupal site login with a user that is authorized to create them (by default only the 1 (admin) user) and go to Configuration->OAuth->Add Context and create something like the following:

$context = new stdClass();
$context->disabled = FALSE; /* Edit this to true to make a default context     disabled initially */
$context->api_version = 1;
$context->name = 'oauth_login';
$context->title = 'OAuth login';
$context->authorization_options = array(
  'access_token_lifetime' => NULL,
  'page_title' => 'Login to @appname',
  'message' => 'Hi @user! Click on the "login" button to log in to @appname. This will log you in to @appname and give it access to details like your username and email, but not to your password.',
  'warning' => 'Click here if you didn\\\'t ask to be logged in to @appname.',
  'deny_access_title' => 'Cancel',
  'grant_access_title' => 'Login',
  'disable_auth_level_selection' => NULL,
  'signature_methods' => array(
    0 => 'HMAC-SHA1',
    1 => 'HMAC-SHA256',
    2 => 'HMAC-SHA384',
    3 => 'HMAC-SHA512',
  ),
  'default_authorization_levels' => array(
    0 => 'user_info',
  ),
);
$context->authorization_levels = array(
  'user_info' => array(
    'name' => 'user_info',
    'title' => 'Yes, I want to log in to @appname as @user',
    'default' => 1,
    'delete' => 0,
    'description' => 'This will log you in to @appname and give it access to details like your username and email, but not to your password.',
  ),
);

My best guess is that this is the actual page that will be showed to the users that are trying to login, even though I am not sure of this (please comment if I am wrong or if you have further details).

When you have a context go to the profile of your current user (the one that has the rights to edit the authorization stuff) Profile->Authorization->Add Consumer. Give the consumer a name does not matter, jet using the name of the site/application it is for seems logical. As a call back URL use the URL you want the provider to refer to on the consumer side, so when the user logsin, accepts and all is well, the provider will send the oauth token here. Select the freshly created context and click save.

After saving this you can view the consumer Key and secret by clicking edit. These keys you need to build your actual consumer so keep them at hand.

OAuth-PHP Two-legged Authentication

Placing a file, like the one showed below, in the folder where OAuth-PHP lib is stored and accessing it in your browser should output something like this:

----creating an Oauth Requestor----

----do the request----

----save the body for printing----

##oauth_token=WEG7sXcyApS3FqJ2CQMXJW7Zav2B7ZGH&oauth_token_secret=7hTgM6HsnjLTL4spb4XjeS8FYaMAsXVr##

Example File

<?php
//Test Drupal Oauth 1

//include the needed oauth libs.
include_once "oauth-php/library/OAuthStore.php";
include_once "oauth-php/library/OAuthRequester.php";

//The key and secret of our Drupal_test povider.
$key = '3GpmquRX6s8aiTP3aBrK3CM2gmAmNRC9';  //These are the once you can  find in the
$secret = 'iRu6MehmmygRe6NEu24Q7VnPgcm463py'; // edit consumer section in Drupal.

// build the nessesary array
$options = array( 'consumer_key' => $key, 'consumer_secret' => $secret );

//Create an instance that uses 2leg auth and uses the key and secret given
OAuthStore::instance("2Leg", $options );


$url = "http://localhost/drupal7/oauth/request_token"; // this is the URL of the request
$method = "POST"; // you can use POST aswell
$params = null; //no extra params for this test.

$response = null;

try
{

        echo "----creating an Oauth Requestor----\n";
        // Obtain a request object for the request we want to make
        $request = new OAuthRequester($url, $method, $params);

        echo "----do the request----\n";
        // Sign the request, perform a curl request and return the results, 
        // throws OAuthException2 exception on an error
       // $result is an array of the form: array ('code'=>int, 'headers'=>array(), 'body'=>string)
        $result = $request->doRequest();

        echo "----save the body for printing----\n";
        $response = $result['body'];
        echo "##".$response."##";
} catch(OAuthException2 $e) {
  echo "Error: ". $e;
}

?>

Three-legged Authentication

NOTE!!! before you can use OAuth-PHP for three-legged authentication you need to set up DB access. For MySQL create a DB and user (if you want you can of course use an existing one) and edit “oauth-php/library/store/mysql/install.php” to reflect your current setup. Go to this file in your browser and all should be fine (check your DB if the tables are created).

CREATE DATABASE oauth;
GRANT ALL ON oauth TO oauth@localhost IDENTIFIED BY ‘password’;
FLUSH PRIVILEGES;

during testing one can check the database if the data actually shows up there.

Install.php

uncomment this and edit it:

mysql_connect('localhost', 'user', 'password’');
if (mysql_errno())
{
  die(' Error '.mysql_errno().': '.mysql_error());
}
mysql_select_db('oauth');

Example File

<?php
//Test Drupal Oauth 1 three legged

include_once "oauth-php/library/OAuthStore.php";
include_once "oauth-php/library/OAuthRequester.php";

//get a store singelton
$options = array('server' => 'localhost', 'username' => 'drupal',
                 'password' => 'drupal',  'database' => 'oauth');
$store   = OAuthStore::instance('MySQL', $options);

//set the consumer_key
$consumer_key = '3GpmquRX6s8aiTP3aBrK3CM2gmAmNRC9';
// Get the id of the current user (must be an int)
$user_id = 2;

$store = OAuthStore::instance("MySQL", $store_options);

$server = null;
try {
  $server = $store->getServer($consumer_key, $user_id);
} catch (OAuthException2 $e) {
    $server = array(
        'consumer_key' => $consumer_key,
        'consumer_secret' => 'iRu6MehmmygRe6NEu24Q7VnPgcm463py',
        'server_uri' => 'http://localhost/drupal7/oauthlogin/api',
        'signature_methods' => array('HMAC-SHA1', 'PLAINTEXT'),
        'request_token_uri' => 'http://localhost/drupal7/oauth/request_token',
        'authorize_uri' => 'http://localhost/drupal7/oauth/authorize',
        'access_token_uri' => 'http://localhost/drupal7/oauth/access_token'
    );

    $store->updateServer($server, $user_id);
}

//This is just to show a working retreive
$consumer_key = $server['consumer_key'];

// Obtain a request token from the server
$token = OAuthRequester::requestRequestToken($consumer_key, $user_id);

// Callback to our (consumer) site, will be called when the user finished the authorization at the server
$callback_uri = 'http://localhost/oauth-test/three-leg-test-callback.php'; //should be the same as in Drupal

//?consumer_key='.rawurlencode($consumer_key).'&usr_id='.intval($user_id);

// Now redirect to the autorization uri and get us authorized
if (!empty($token['authorize_uri']))
{
    // Redirect to the server, add a callback to our server
    if (strpos($token['authorize_uri'], '?'))
    {
        $uri = $token['authorize_uri'] . '&';
    }
    else
    {
        $uri = $token['authorize_uri'] . '?';
    }
    $uri .= 'oauth_token='.rawurlencode($token['token']);    
}
else
{
    // No authorization uri, assume we are authorized, exchange request token for access token
   $uri = $callback_uri . '&oauth_token='.rawurlencode($token['token']);
}

header('Location: '.$uri);
exit();
?>

Callback Example (this is the file that should be in your Consumer call back URL mentiond in the chapter Consumer)

<?php
//Test Drupal Oauth 1 three legged

include_once "oauth-php/library/OAuthStore.php";
include_once "oauth-php/library/OAuthRequester.php";

//get the store
$store_options = array('server' => 'localhost', 'username' => 'drupal',
                 'password' => 'drupal',  'database' => 'oauth');
$store = OAuthStore::instance("MySQL", $store_options);

//Exchange your Request Token for an Access Token
$consumer_key = '3GpmquRX6s8aiTP3aBrK3CM2gmAmNRC9';
$user_id = 2;

try
{
  //this is stored in the DB
  OAuthRequester::requestAccessToken($consumer_key, $_GET['oauth_token'],     $user_id);
}
catch (OAuthException $e)
{
  // Something wrong with the oauth_token.
  // Could be:
  // 1. Was already ok
  // 2. We were not authorized

}


?>

Q1: After all this you should be authenticated, However Drupal should send you a OAuth_token and a OAuth_token_secret by my understanding of it all. It only sends a OAuth_token though, can anyone tell me why?

Q2: Furthermore a lot of examples stop her, why is that? If I look at the OAuth shema to get authorization with external services (what OAuth is for), this is only the start. Is this as far as we go to get authenticated by an external source? Or is this as far as two-legged authentication goes?

  • I did the same thing and i found out that the Oauth_token_secret didn't contain in session or URL or variables. It stored in the oauth_common_token table. With the current oauth_token you can query and get the oauth_token_secret. – Stone Vo Sep 12 '13 at 4:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.