Google Chrome 拡張機能でOAuthを利用する方法

記事について

GoogleカレンダーAPIを使って拡張機能を作りたかったけど、OAuthでの認証が必要と分かった。色々調べていると認証が通ったので、そのメモ書き。

拡張機能でOAuthを利用する際に問題になること

  1. CONSUMER_KEYやCONSUMER_SECRETを公開してしまうこと
  2. 認証の際に別URLへコールバックされること

1に関して。
Googleのカレンダーやコンタクトや何やらのGoogle Data APIを叩きたかったら、OAuthで認証する必要がある。OAuthは通常CONSUMER_KEYやCONSUMER_SECRETをサービス提供側が事前に取得する必要がある。この2つのキーは他人に公開すると悪用される場合があるため、教えてはならない。

2に関して。
OAuthの仕様上、認証に必要なキーを取得するためにコールバックで別のURLを飛ばされてしまう。コールバックのURLにはhttp://*https:// しか指定できず、Chrome拡張機能を示すchrome-extension://*は指定できない。

解決策

問題1の解決策は、CONSUMER_KEYとCONSUMER_SECRETに両方'anonymous'を入れるだけ。
問題2に関して。
Chrome APIのサンプルにOAuth機能を実現するサンプルが有る。Sample - OAuth Contacts
このサンプルを実行するとユーザのコンタクト情報が取得できたことが分かる。今回はこの中の

3ファイルを利用する。これらのファイルは拡張機能でOAuthを実現するために必要なファイルである。chrome_ex_ouath.htmlはコールバック先のファイルである。内部でどういった動作をしているかはわからないので、解説はできない。

実装

以下のプログラムはGoogleカレンダーAPIを使い予定を登録するプログラムである。
まずmanifest.jsonにはこのように書く。

{
    ...
    "background_page": "background.html",
    "permissions": [
        "tabs",
        "http://www.google.com/calendar/feeds/*",
        "https://www.google.com/accounts/OAuthGetRequestToken",
        "https://www.google.com/accounts/OAuthAuthorizeToken",
        "https://www.google.com/accounts/OAuthGetAccessToken"
    ],
    ...
}

background.htmlで認証処理を行わせる。認証の際にドメインを複数またぐので、その許可を求める。
今回はGoogleOAuth認証を行うのでそれ用の設定をしたが、Twitterに関しては別の方が書かれていた。Loading...

background.htmlで行わせる処理。

...
<script src="OAuthSimple/chrome_ex_oauth.js"></script>
<script src="OAuthSimple/chrome_ex_oauthsimple.js"></script>
<script>
var oauth = ChromeExOAuth.initBackgroundPage({
        'request_url' : 'https://www.google.com/accounts/OAuthGetRequestToken',
        'authorize_url' : 'https://www.google.com/accounts/OAuthAuthorizeToken',
        'access_url' : 'https://www.google.com/accounts/OAuthGetAccessToken',
        'consumer_key' : 'anonymous',
        'consumer_secret' : 'anonymous',
        'scope' : 'http://www.google.com/calendar/feeds/',
        'app_name' : 'Application Name'
});
window.chromeExOAuth.callback_page = 'OAuthSimple/chrome_ex_oauth.html';

oauth.authorize(function() {
    var url = "http://www.google.com/calendar/feeds/default/private/full";
    var body = JSON.stringify({
        "data": { "title": "Tennis with Beth",
            "details": "Meet for a quick lesson.",
            "transparency": "opaque",
            "status": "confirmed",
            "location": "Rolling Lawn Courts",
            "when": [
            {
                "start": "2010-04-17T15:00:00.000Z",
                "end": "2010-04-17T17:00:00.000Z"
            }
            ]
        }
    });
    oauth.sendSignedRequest(url,
    function(text, xhr) {
        console.log(text);
    },
    {
        'method': 'POST',
        'headers': {'GData-Version': '2', 'Content-Type': 'application/json'},
        'body': body
    });
});

...
</script>
...

ChromeのOAuthサンプルのファイルを読み込ませる。その後に、ChromeExOAuth.initBackgroundPage APIを使い認証の設定させる。問題1の解決策で書いたようにconsumer_keyとconsumer_secretに'anonymous'を入れる。
次の行に関してだが、これはコールバックURLの変更する手続きである。コールバックURLのデフォルトは'chrome_ex_oauth.html'となっている。変更するオプションも同APIに存在するが、変更出来なかった。chrome_ex_oauth.jsの関係するコードを読むと設定方法が分かった。windos.chromeExOAuth.callback_pageに任意のコールバックURLを入れることで設定ができた。

oauth.authorizeで認証を行わせる。引数の関数はtokenが取得できた時に呼ばれる関数である。ここで初めて、GoogleカレンダーAPIを使い予定を登録したり取得することが可能となる。

最後にGoogle カレンダーAPIを使い予定を登録する。そのためのAPIこれ。POSTメソッドを使い予定を送信する。この時JSONフォーマットで送るので

Content-Type: application/json
GData-Version: 2

とした。このヘッダ情報に加えてGoogle Data APIのバージョンも追加しておいた。今回のプログラムではバージョン情報を追加しなくとも動くことが確認できた。

これらの情報を送信するAPIはoauth.sendSignedRequestである。引数はそれぞれ、APIのURL、送信後のレスポンスを受け取る関数、送信情報である。

終りに

GoogleカレンダーAPIをつかって予定を登録することができた。手こずったのは予定を登録する処理である。APIのドキュメントを読みながらやっていたからである。

以上メモ書き。