hello, onedrive

OneDrive にも対応するようにした。OneDrive というのはかつては SkyDrive とよばれていた、Microsoft が提供するオンラインストレージだ。

そのためにドキュメントをいろいろ参照するわけなのだけど、まあいつもの MSDN クオリティというか、量自体は豊富なんだけど痒いところに手が届かない感じがしてあんまり使いやすくない。

あと、OAuth での認可を受けるためのエンドポイントのドメインが login.live.com なのに OneDrive(というか Live Connect)の API は apis.live.net だったりちぐはぐなのがなんか全体的にこう……なんと言ったらいいのか MS らしいですね!

かつて apple の親分だったおじさんが MS を評して曰く、「彼らはセンスが足りないんじゃない。『ない』んだ」とかなんとか、と聞いたことがあるけれど、もしかしたら、まったくもって、その通りなのかもしれない。

OAuth 2.0 in a browser extension

アプリケーションが OAuth 2.0 における認可を得る際の手順は、そのアプリケーションの性格によっていくつかの系統に分かれる。このあたりは google のドキュメントなどにまとまっているのだが、つまり

  • Web サーバが主体になる場合
  • ネイティブアプリケーションが主体になる場合
  • ブラウザが主体になる場合

と大別される。いずれにしても、基本的には

  1. 認可を得るための一時的なコードを得るための最初のリクエスト(これは正確には認可を得るためのページを web ブラウザで開くだけの処理だ。認可を得るかどうかはそのページを見ているユーザが判断する)
  2. そのコードをアクセストークンへ交換するための 2 度目のリクエスト
  3. 得たアクセストークンが正しいものであるかの確認のリクエスト(これは認可を得るための必須の処理ではないけれど、普通は行う)

を順に行うという流れに従うのだが、何が主体になるかで微妙なところが微妙に違う。具体的には、一時的なコードを得るための経路や、アプリケーションごとに割り当てられるクライアント ID、クライアントシークレットの扱いなどだ。

  • Web サーバが主体になる場合、リクエスト 1 の際にリダイレクト URL を指定する。この URL として、Web サーバの管理が及ぶ適当なものを与える。アプリケーションを利用するユーザが承認すると、ユーザが見ているブラウザのページは自動的にリダイレクト URL に転送される。このとき、URL に追加されているクエリ文字列に一時コードが含まれているので、Web サーバはそれを得ることができる。
  • ネイティブアプリケーションが主体になる場合、Web サーバのようには行かないので、2 つの特殊なリダイレクト URL のどちらかを使用する。[cci]urn:ietf:wg:oauth:2.0:oob[/cci] を指定した場合は、何やら呪文のようなアドレスだが、つまりリクエスト 1 の時点で単にページ上に一時コードを表示して一旦終了ということだ。これをユーザが手作業でアプリケーションにコピペする。[cci]http://localhost[/cci] を指定した場合は、あらかじめネイティブアプリケーションがローカルマシンの適当なポートをリスンしておき、その経路を通して一時コードを得る。
  • ブラウザが主体になる場合は特殊で、一時コードをすっ飛ばしていきなりアクセストークンを得ることができてしまう。ただしこれで得たアクセストークンは非常に短い有効期間しか持っていない。

と、ここまでは、上のドキュメントに書いてあることそのままなので、いいのである。問題は、ブラウザに組み込まれるエクステンションの場合はどのシナリオを選択すればいいの? ということだ。

エクステンションは単なるブラウザ上のスクリプトよりも多くの機能を持っているので、ブラウザだからといってブラウザ主体のシナリオのみ許されるわけではない。それどころか、とても興味深いことに、ブラウザのエクステンションは工夫次第によって 3 つのシナリオを全てを実装できてしまう。そして同時に、いずれの方式にも若干の気をつけるポイントも出てくる。どれを選択するべきなのか?

 * * *

Web サーバシナリオを選択した場合、適当な外部の Web サーバを用意し、リダイレクト URL を作る。エクステンションはリクエスト 1 によるアクセスにまつわるブラウザのページ遷移を監視し、リダイレクト URL に達した時点でクエリ文字列を得ればいい。これに嫌な点があるとすると、一時コードを含んだ URL が認可サーバからブラウザに来るパスの他にもう一度、ネットワークを流れてしまうということだ。そのためリダイレクト URL を SSL 経由にしたりする必要があるが、これはなかなかコストのかかる作業である。

ネイティブアプリケーションシナリオを選択した場合、外部 Web サーバは不要だ。ブラウザのリダイレクトを [cci]oob[/cci] にし、ページに一時コードが表示された時点でエクステンションからそれを読み取ればいい(このへんがちょっとハックでストレートじゃないのが気になるが)。一方で、これは Web サーバシナリオでも実質的に同じだが、クライアント ID とクライアントシークレットをエクステンションのパッケージに内包させなければならないのが気になる。全然シークレットでもなんでもなくなってしまうのである(これは、上のドキュメントにも書いてあることであるが、ネイティブアプリケーションシナリオにおいてはどうにもならない副作用だ)。

wasavi は dropbox のクライアント情報に関しては、エクステンションのパッケージ内に暗号化して含めるようにしている。これはプレーンな状態で含めようとしたら dropbox の審査で暗号化しろよ! と怒られたのでそうした経緯があるのだが、しかしまあ、ブラウザのエクステンションである。すなわち javascript コードがそのまま入ってるのである。コードを読めば、どう復号するのかはすぐわかっちゃうわけで、意味があるのかどうかはいまいちわからない。

最後のブラウザシナリオでは上に書いたような問題点は一見ない。アクセストークンを得るためにクライアントシークレットは不要だ(クライアント ID は必要なのでこのあたりの問題が根本的に解決するわけではない)。しかしこの形式で得たアクセストークンは前述したとおりすぐ切れる。wasavi では Google Drive との接続はこの方式を用いているのだが、だいたい 1 時間もするとすぐに再認可のページに飛ばされてしまう。これは使い勝手が良いとはちょっと言えない。