OAuth2.0が登場してからも、1.0を採用し続けるwebサービスはTwitter、Tumblr、500pxなど、まだまだ数多く残っています。今回は「OAuth 1.0認証における署名(Signature)の作成方法」を紹介します。なお、この記事で説明する署名の作成方式は「HMAC-SHA1」です。

目次

  1. 署名とは?
  2. HMAC-SHA1とは?
  3. 必要な要素
  4. 署名作成の3ステップ
  5. サンプルリクエスト
  6. キーを作成する(3件)
    1. 出来上がったキー
    2. oauth_token_secretがない場合
    3. サンプルプログラム(PHP)
  7. データを作成する(6件)
    1. パラメータを組み立てる
    2. パラメータをエンコード
    3. メソッドをエンコード
    4. リクエストURLをエンコード
    5. 3つの要素を[&]で繋ぐ
    6. サンプルプログラム(PHP)
  8. キーとデータを使って署名を作成する(3件)
    1. HMAC-SHA1方式のハッシュ値に変換
    2. ハッシュ値をbase64エンコード
    3. サンプルの署名
  9. 完成版プログラム(PHP)(2件)
    1. 署名を作成する関数
    2. 関数の使い方
  10. OAuth1.0の署名は簡単に作れる

1署名とは?

「OAuth1.0」という認証方式を採用したAPIを利用する場合、リクエストするパラメータに応じて、「署名(Signature)」となるキー(暗号)を作成し、一緒に送信しなければいけません。APIを提供するサービス側は、アプリケーション側が送ってきたパラメータと、この署名を照合し、署名が正しくない場合、エラーを返します。

OAuth OAuth
OAuthの公式サイト、仕様書。今は読む必要はありません。というか私は一度も読んでません。

OAuth Wikipedia
簡潔に概要がまとめられています。興味がある場合はこちらを読んでみて下さい。なんとなくの理解で大丈夫です。

2HMAC-SHA1とは?

「HMAC-SHA1」とは、データの変換方式の1つです。「料理」に例えると分かりやすいかもしれません。例えば、魚という食材があって、「フライパン」で作ると焼き魚になりますよね。「鍋」で作ると煮魚になります。データはここでいう魚、「HMAC」はフライパンや鍋、そして「SHA1」はフライパンや鍋の種類、にあたります。

OAuth1.0における署名を作成するには、この「HMAC-SHA1」という製法が多く用いられているというわけです。HMAC-SHA1製法を覚えておけば、世の中のOAuth1.0を採用したAPIのほとんどに対応できるはずです。

HMAC Wikipedia
興味がある人向けにWikipediaのリンクを用意しましたが、私は興味ないので読んでません(笑)。

hash_hmac — HMAC 方式を使用してハッシュ値を生成する PHP公式マニュアル
PHPを用いて、HMAC製法(Sha1)を利用する方法です。

3必要な要素

OAuth1.0における認証には通常、下記4つの値が必要です。その内、純粋に署名を作成する部分だけを見れば「oauth_consumer_secret」と「oauth_token_secret」が必要となります。「oauth_token_secret」に関しては、存在しない場合、空白にします。

項目 説明
oauth_consumer_key アプリケーションごとに割り当てられたID。webサービスによって「API Key」「Consumer Key」など名称が違う。
oauth_consumer_secret oauth_consumer_keyの対となるキー。webサービスによって「API Secret」「Consumer Secret」など名称が違う。
oauth_token アプリケーションを利用するアクセス、ユーザーごとに割り当てられたID。「アクセストークン」など。
oauth_token_secret oauth_tokenの対となるキー。「アクセストークンシークレット」など。

4署名作成の3ステップ

署名の作成は一見複雑に見えますが、その実は、下記の3ステップで構成される「単純な作業」です。「キー」と「データ」の作り方、そして「変換方法」を覚えてしまいましょう。

  1. 「キー」を作成する
  2. 「データ」を作成する
  3. 「キー」と「データ」を、「HMAC-SHA1」を用いて署名に変換する

5サンプルリクエスト

ここからは、サンプルを用いて実際にOAuth1.0における署名(HMAC-SHA1方式)を作成していきます。下記が今回、利用するサンプルリクエストです。

項目 説明
リクエストURL http://example.com/sample.php
リクエストメソッド POST方式
パラメータ
([名前]:値)
[title]:AAA
[name]:BBB
[text]:CCC

また、次の値の「oauth_consumer_secret」「oauth_token_secret」を所有していると仮定します。

項目
oauth_consumer_secret bbbbbb
oauth_token_secret dddddd

6キーを作成する

「HMAC-SHA1」という変換方式を用いるためには、「データ」と「キー」が必要です。まずは「キー」を作成してみましょう。その作り方は簡単で、「oauth_consumer_secret」と「oauth_token_secret」をURLエンコードして、&で繋げるだけです。

6-1出来上がったキー

サンプルを元にすると、次が署名の「キー」となります。

「oauth_consumer_secret」と「oauth_token_secret」の値は通常、英数字になるので、URLエンコードをしても実質的に意味はありません。が、定義上そうなっていることを覚えておきましょう。

6-2oauth_token_secretがない場合

OAuth1.0認証をしている上で、「oauth_token_secret」の値が存在しないケースに出くわすことがあります。その場合は、次のように「oauth_token_secret」を空白にしてキーを作成して下さい。

6-3サンプルプログラム(PHP)

PHPを利用して署名キーを作成するには、次のようにプログラミングします。

<?php
//oauth_consumer_secret
$oauth_consumer_secret = "bbbbbb";

//[oauth_consumer_secret]をURLエンコード
$encode_a = rawurlencode($oauth_consumer_secret);

//oauth_token_secret
$oauth_token_secret = "dddddd";

//[oauth_token_secret]をURLエンコード
$encode_b = rawurlencode($oauth_token_secret);

//2つの値を[&]で繋いで署名キー[$signature_key]が完成する
$signature_key = "{$encode_a}&{$encode_b}";

プログラム中の関数について

rawurlencode — RFC 3986 に基づき URL エンコードを行う PHP公式マニュアル
[rawurlencode]は、URLエンコードをする関数です。

7データを作成する

続いて「データ」を作成していきましょう。作成方法は次の通りです。

  1. 「パラメータ」をアルファベット順に「名前=値&名前=値&...」と繋ぐ。
  2. 組み立てた「パラメータ」をURLエンコードする。
  3. 「リクエストメソッド」をURLエンコードする。
  4. 「リクエストURL」をURLエンコードする。
  5. 「リクエストメソッド」「リクエストURL」「パラメータ」の順番に&で繋げる。

7-1パラメータを組み立てる

まずは1番です。パラメータをアルファベット順に、「名前=値&名前=値&...」という形式に組み立てます。サンプルを用いると、「name」「text」「title」をアルファベット順に並び替えて次のようになります。

7-2パラメータをエンコード

続いて、組み立てたパラメータをURLエンコードします。すると次のようになります。

7-3メソッドをエンコード

リクエストメソッドをURLエンコードします。実質的に意味はありませんが、形式的に行なっておきましょう。サンプルを元にすると次の通りです。

7-4リクエストURLをエンコード

続いて、リクエストURLをURLエンコードします。サンプルを元にすると次の通りです。

7-53つの要素を[&]で繋ぐ

最後に、「リクエストメソッド」「リクエストURL」「パラメータ」の順番に&で繋げます。サンプルでは次の通りになります。分かりやすいように色分けをしてあります。

これで「データ」が出来上がりました。特別に難しいことはなかったと思います。

7-6サンプルプログラム(PHP)

PHPを利用してデータを作成するには、次のようにプログラミングします。

<?php
//リクエストメソッド(URLエンコード)
$request_method = rawurlencode('POST');

//リクエストURL(URLエンコード)
$request_url = rawurlencode('http://example.com/sample.php');

//パラメータ(連想配列形式)
$params = array(
	'title'=>'AAA',
	'name'=>'BBB',
	'text'=>'CCC',
);

//連想配列のキーをアルファベット順に並び替える
ksort($params);

//連想配列[$params]を[キー=値&キー=値]の形式に組み立てる
$request_params = http_build_query($params,'','&',PHP_QUERY_RFC3986);

//組み立てたパラメータをURLエンコードする
$request_params = rawurlencode($request_params);

//メソッド[$request_method]、URL[$request_url]、パラメータ[$request_params]の順に[&]で繋げる
$signature_data = "{$request_method}&{$request_url}&{$request_params}";

プログラム中の関数について

ksort — 配列をキーでソートする PHP公式マニュアル
[ksort]は、連想配列のキー名を基にアルファベット順にソートすることができます。

http_build_query — URL エンコードされたクエリ文字列を生成する PHP公式マニュアル
連想配列を[キー=値&キー=値...]という文字列に変換することができます。

8キーとデータを使って署名を作成する

仕上げに、作成した「データ」と「キー」を使って、署名を作成します。次のような手順になりますが、1つ1つの処理、内容は現段階ではよく分からないままで大丈夫です。

  1. 「データ」「キー」を用いて、HMAC-SHA1方式のハッシュ値に変換する。
  2. ハッシュ値をbase64エンコードする。

8-1HMAC-SHA1方式のハッシュ値に変換

まず、「データ($signature_data)」と「キー($signature_key)」を使って、HMAC-SHA1方式のハッシュ値に変換します。PHPでは次の通りになります。

$hash = hash_hmac('sha1',$signature_data,$signature_key,TRUE);

8-2ハッシュ値をbase64エンコード

最後に、出来上がった「ハッシュ値($hash)」を、base64エンコードして、署名の完成となります。

$signature = base64_encode($hash);

8-3サンプルの署名

サンプルを元にした署名は次の通りとなります。

9完成版プログラム(PHP)

毎回、署名作成の処理を記述するのは大変ですよね。そこで、これまでに説明してきた「署名の作り方」を、PHPの関数に反映しましょう。よろしければ、ご利用下さい。

9-1署名を作成する関数

こちらが、作成してみた関数です。

<?php
//引数に配列を指定して呼び出す関数 [make_oauth_signature_syncer]
//make_oauth_signature_syncer(array(
//	'oauth_consumer_secret' => '',	//oauth_consumer_secret
//	'oauth_token_secret' => '',	//oauth_token_secret
//	'request_method' => '',	//リクエストメソッド
//	'request_url' => '',	//リクエストURL
//	'request_params' => array(),	//リクエストパラメータ(連想配列形式)
//));

function make_oauth_signature_syncer($item){
	//キーを作成
	$signature_key = rawurlencode($item['oauth_consumer_secret']).'&'.rawurlencode($item['oauth_token_secret']);

	//データを作成
	ksort($item['request_params']);
	$signature_data = 	rawurlencode($item['request_method']).'&'.rawurlencode($item['request_url']).'&'.rawurlencode(http_build_query($item['request_params'],'','&',PHP_QUERY_RFC3986));

	//署名を作成して返却
	return base64_encode(hash_hmac('sha1',$signature_data,$signature_key,TRUE));
}

9-2関数の使い方

関数の使い方を紹介します。例えば、この記事で紹介したサンプルリクエストを署名に変換するには、次のように関数を呼び出して下さい。$signatureに作成した署名が格納されます。

<?php
$signature = make_oauth_signature_syncer(array(
	'oauth_consumer_secret' => 'bbbbbb',	//oauth_consumer_secret
	'oauth_token_secret' => 'dddddd',	//oauth_token_secret
	'request_method' => 'POST',	//リクエストメソッド
	'request_url' => 'http://example.com/sample.php',	//リクエストURL
	'request_params' => array(	//リクエストパラメータ(連想配列形式)
		'title'=>'AAA',
		'name'=>'BBB',
		'text'=>'CCC',
	),
));

10OAuth1.0の署名は簡単に作れる

お疲れ様でした。OAuth1.0の署名は、取っ付き難いものの、仕組みが分かってしまえば簡単に作成することができます。ネット上に用意されているライブラリを利用するのは時間短縮という意味では有効ですが、応用力を身に付けるという意味で1からプログラミングすることに挑戦してみてはいかがでしょうか。この記事が、あなたが作る素敵なwebサービスの一助になれば幸いです。