Tumblr API OAuth認証の方法（PHPサンプル付き）

# Tumblr APIの認証について
Tumblr APIは、[Oauth 1.0a](http://oauth.net/core/1.0a/)で認証して各種APIを利用するが、[Tumblr APIドキュメント](https://www.tumblr.com/docs/en/api/v2)では、OAuth認証でよろしくやってちょうだい程度しか書かれておらず、懇切丁寧には説明してくれていない。Tumblrがやってくれないようなので、私がアプリケーションの登録、OAuth認証、APIコールまでをサンプルコード付きで、Tumblrに代わり懇切丁寧に説明したい。なお本稿は、WEBアプリケーションでのTumblr APIの利用を想定し、サンプルコードはPHPで記載したいと思う。
# アプリケーション登録
APIを利用するにあたり使用するアプリケーションを、Tumblrの管理画面より登録する必要がある。
[Tumblr アプリケーション管理画面](https://www.tumblr.com/oauth/apps)

## 登録画面へ
管理画面で「+アプリを登録する」ボタンを押下。

## 登録画面で各種情報を取得
アプリ登録画面で各種情報を入力する。

| 項目名 | 説明 | 必須 |
|:-----------|:------------|:------------:|
| アプリケーション名 | 任意のアプリケーション名 |     ○     |
| アプリケーションウェブサイト |アプリケーションのURL|    △[^1]    |
| App Store URL      |App StoreのURL|     △[^1]     |
| Google Play Store URL     |Google Play StoreのURL |      △[^1]      |
| アプリケーションの説明      | アプリケーションに関する説明文 |      ○      |
| 管理用の連絡先メール        |管理者のメールアドレス |      ○      |
| デフォルトのコールバックURL | Tumblrの認証画面で認証後に戻るコールバックURL |      ○      |
[^1]: 「アプリケーションウェブサイト」「App Store URL」「Google Play Store URL」のいずれかの入力が必須。まだ無い場合には、「アプリケーションウェブサイト」に "http://localhost/" とでも入力しておけばよい


入力後に登録ボタンを押下

## アプリ一覧画面でコンシューマーキーの取得
アプリ登録後、アプリケーション一覧に今登録したアプリが表示されるはず。そこに表示されている、「Consumer Key」と「Secret Key」がAPIをコールするために必要となるためメモをとる。なお「Secret Key」はデフォルトでは表示されておらず、「Show secret key」というテキストをクリックする必要がある点に注意。

![app_secret.png](https://qiita-image-store.s3.amazonaws.com/0/57879/c998744c-cd5d-53ae-72c2-b4845355e9f7.png)

# OAuth認証
Tumblrで使用されているOauthのバージョンは前述の通り、Oauth 1.0aを使用している。簡略化されたOAuth 2.0に比べトークンのやり取りが少々煩雑である。本来は、Oauth 1.0aの登場人物である「Service Provider」「User」「Consumer」に対して、フロー図とかを書いてOauth 1.0aの概念及び概要を示すのが適切と思う。が、うまくやれる自信が無いので、そもそもアプリケーション側は何をすればいいかにフォーカスして以下に記載したい。

1. コンシューマーキーを使って、[リクエストトークン取得URL](http://www.tumblr.com/oauth/request_token)からリクエストトークンを取得する
2. リクエストトークンは、コールバックしてきた後でも使うのでセッションにでも保存しておく
3. リクエストトークンを使って、[認証用URL](http://www.tumblr.com/oauth/authorize)にリダイレクトさせる
4. そうするとユーザーのブラウザには「このアプリケーションがデータにアクセスしてあなたのアカウントに投稿することを許可しますか？」というTumblr側の認証画面が出る
5. 「許可ボタン」が押されると、アプリケーション登録時に設定したコールバックURLにリダイレクトされてくる
6. セッションに保存しておいたリクエストトークンを使って、[アクセストークン取得用URL](http://www.tumblr.com/oauth/access_token)からアクセストークンを取得する
7. アクセストークンを使ってAPIをコールする

つまり、あなたの作るWABアプリケーションで、上記項番でいう 1, 2, 3, 6, 7 を実装すればよい。

## PHPでの実装サンプル
PHPでの実装サンプルを例示する。リクエストトークンを取得すると簡単には書いたが実際にはリクエストパラメーターから署名を作る必要があったりと自前で実装する場合は少々面倒。そのためこの実装サンプルではPHPのPECL oauthライブラリを使用している。インストールされていない場合は、適宜インストールのこと。[PHP: OAuth - Manual](http://php.net/manual/ja/book.oauth.php)

### OAuth認証の開始
```php:login.php
<?php
require_once './oauth.php';

$oauth_sample = new OAuthSample();
try {
    // リクエストトークンの取得とリダイレクト開始
    $oauth_sample->goToAuthorize();
} catch (\Exception $e) {
    // エラー処理
}
```


### 各種トークンのやりとりをするクラス
```php:OAuthSample.php
<?php
/**
 * Tumblr OAuth認証実装サンプル
 *
 * @author newton
 */
class OAuthSample
{
    const CONSUMER_KEY       = 'あなたのコンシューマーキー';
    const CONSUMER_SECRET    = 'あなたのコンシューマーシークレット';
    const REQUEST_TOKEN_URL  = 'http://www.tumblr.com/oauth/request_token';
    const AUTHORIZE_URL      = 'http://www.tumblr.com/oauth/authorize';
    const ACCESS_TOKEN_URL   = 'http://www.tumblr.com/oauth/access_token';

    /**
     * コントストラク
     * セッションの初期化をやる
     */
    public function __construct()
    {
        if (!isset($_SESSION)) {
            session_start();
        }
    }

    /**
     * リクエストトークンの取得～リダイレクト
     */
    public function goToAuthorize()
    {
        $oauth = new \OAuth(self::CONSUMER_KEY, self::CONSUMER_SECRET);
        // リクエストトークン取得
        $request_token = $oauth->getRequestToken(self::REQUEST_TOKEN_URL);

        if (!$request_token) {
            throw new Exception('リクエストトークンの取得に失敗');
        }

        // リクエストトークンをセッションに保存する
        $_SESSION['request_token'] = $request_token['oauth_token'];
        $_SESSION['request_token_secret'] = $request_token['oauth_token_secret'];

        $params = ['oauth_token' => $request_token['oauth_token']];
        $path = self::AUTHORIZE_URL . '?' . http_build_query($params);

        $this->redirect($path);
    }

    /**
     * アクセストークンの取得
     * コールバック後にコールされる用
     *
     * @return array アクセストークンのセットされたハッシュ
     */
    public function getAccessToken()
    {
        $oauth = new \OAuth(self::CONSUMER_KEY, self::CONSUMER_SECRET);
        // アクセストークンの取得
        $oauth->setToken($_SESSION['request_token'], $_SESSION['request_token_secret']);
        $access_token = $oauth->getAccessToken(self::ACCESS_TOKEN_URL, $_GET['oauth_verifier']);

        if (!$access_token) {
            throw new \Exception('アクセストークンの取得に失敗');
        }

        return $access_token;
    }

    /**
     * リダイレクト
     *
     * @param string $path   リダイレクト先URL
     * @param int    $status ステータスコード
     */
    private function redirect($path, $status = 302)
    {
        header('Cache-Control: no-store, no-cache, must-revalidate');
        header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
        header("Location: {$path}", true, $status);
        exit;
    }
}
```

### Tumblrからコールバックしてきた後の処理
```php:callback.php
<?php
require_once './oauth.php';

$oauth_sample = new OAuthSample();
try {
    // アクセストークンの取得
    $access_token = $oauth_sample->getAccessToken();

    // 取得できたアクセストークンで試しに、ダッシュボードのAPIをコールしてみる
    $oauth = new \OAuth(OAuthSample::CONSUMER_KEY, OAuthSample::CONSUMER_SECRET);
    $oauth->setToken($access_token['oauth_token'], $access_token['oauth_token_secret']);
    // ダッシュボードを取得するAPIを叩く
    $params = ['offset' => 0, 'limit' => 20];
    $oauth->fetch('http://api.tumblr.com/v2/user/dashboard', $params);
    $response_info = $oauth->getLastResponseInfo();
    if ($response_info['http_code'] == 200) {
        $response = json_decode($oauth->getLastResponse(), true);
    } else {
        throw new \Exception('APIからデータの取得に失敗');
    }
} catch (\Exception $e) {
    // エラー処理
}
// 結果をダンプ
var_dump($response);

```
### サンプルの使い方
つまり、あなたのWEBアプリケーションでログインボタンが押されたら "login.php" を実行して、リクエストトークン取得と認証画面にリダイレクトまで実行。アプリ登録画面で指定したコールバックURLで "callback.php" が実行されるようにしておけば、アクセスキーが取得出来るので各種APIをコール出来るようになる。

# 備考・注意事項
## アクセスキーの取り扱いについて
アクセスキーは、ユーザーのTumblrソースにアクセス可能となるキーである。そのためログインパスワード等と同程度の意識をもってデータを取り扱う必要がある。自動ログイン機能を実装する場合は、DBにアクセスキーを保存する必要がある。その場合は、ちゃんと秘密鍵で暗号化して保存の事。

## xAuthについて
Tumblr APIにはWEBアプリ等での使用を想定したOauth 1.0aでの認証以外にも、アプリでの使用を想定したxAuth認証が用意されている。しかし、デフォルト状態ではxAuthが無効になっているため申請を出してTumblr側に許可をもらう必要がある。[Tumblr アプリケーション管理画面](https://www.tumblr.com/oauth/apps)に、「Request xAuth」というリンクがあるので、そいつをクリックするとテンプレートの本文が入力された状態でメーラーが立ち上がる。そこにどういった用途で使うのかを英文で記入してメールすればいいらしい。私はやった事がないので詳細は知らない。

![app_xauth.png](https://qiita-image-store.s3.amazonaws.com/0/57879/cc45de68-c5db-7fc6-1779-4ec5e6c30e8a.png)

## Tumblrアプリケーションの削除について
この記事を書くために、テスト用のTumblrアプリケーションをホイホイ追加していたのだが、さて削除しようかと思ったら削除ボタンがない。どうも自分では削除できないもよう。気をつけてください。