WSSEチケット認証でGoogleDocsとFederationさせるGoogleDocsとGAEの連携GoogleDocsやGoogleAppsとGAEは相性がよく、これらを組み合わせたアプリを作りたいと考えている方も多いだろう。3層アーキテクチャーを基本にしたマッシュアップアプリが作れないか日々、研究している。Apps向けマーケットを開設なんて発表があった。Docsについては、先日、すごいのはGDriveより全文検索でしょ!?にも書いたが、PDFやEXCELといった様々なタイプのコンテンツをほぼ無制限に格納でき、かつ全文検索もできるので大変便利である。Editionでなくても実質的にAnyTypeを扱えている。AppsとGAEを連携させるのは非常に有効なのだが若干問題もある。一つには、Google認証だけでは、サイトを跨ぐ認証機能が不十分でうまくアプリケーションを連携できないこと。Docsの大きなサイズのコンテンツを扱えないこと。これを解決するには、OAuthのような、サイトを跨ったアクセス権(認可)委譲の仕組みが必要となるが、OAuthを使ったとしても第3者の所有するリソースにはアクセスできない。そこで、下図のようなWSSEチケットを使った仕組みで解決してみることを考えた。Docsにユーザのアクセス権を付与することで第三者によるコンテンツ取得を可能にするものである。狭い意味でシングルサインオンのことであるが、第三者への認可を行えるという意味では別物と考えてもらいたい。WSSEは、WS-Securityと実質的に同じものであり、古くから存在するがあまり普及していない。Pubで本命視されながら結局採用されなかった。<やりたいこと>ユーザYはサービスプロバイダZのコンテンツを取得したい。YはコンシューマXのアカウントである。ZはYのことを知らないし知ってはいけない。ZにとってYからのリクエストはXコンシューマからのリクエストとして処理しなければならない。一方で、コンテンツ取得の際はXを経由せずに行いたい。(1MB制限回避のため)ZのコンテンツはXに対して常に開放されているわけではなく、普段は閉じられていてリクエストがあってはじめて提供できるようにしたい。課金などに使うためアクセスログも取りたい。Appsの一員である。DocsのACLに追加されてREAD権限がつく。ダウンロード後(数分後)サービスプロバイダが登録したTaskQueueによりXドメインのREAD権限が削除される。DocsのACLには、Googleアカウントかドメイン名のどちらかを指定する。Editionを除く)からはできない。今回のケースでは、ZはYのことを知ってはいけないので、Xのドメイン名を追加する方法をとった。ユーザのアクションによりブラウザから以下のGETメッセージがコンシューマに飛ぶ。すると、コンシューマはWSSEリダイレクトURLを生成してブラウザに返す。302)であり、これを受けたブラウザは自動的にプロバイダに遷移する。nonceはランダムな値、createdは作成日時、userはXユーザである。URLを受けたサービスプロバイダは、保持しているXアカウントのpaswordとnonceとcreatedを結合してSHA1でハッシュ値を計算し、digestと比較する。一致すれば認証成功、一致しないか、既に使用済みのdigestであれば認証失敗としてブラウザに結果を返す。(digestはDatastoreに記録するなどして使用済かどうかを判定する)(パスワードを保持しているのはコンシューマXのサーバ内であり、ユーザYにはワンタイムだけ有効なハッシュ値だけが渡されるのがミソ。チケットを発行するには、必ずXサーバにログインしなければならないので、この時点で認可されていると考えてよい。認証成功の場合、以下のような実際のダウンロードURLを返す。Docsにもログインしていなければ、ダウンロード失敗となる。これの回避方法は後ほど述べる。idが一瞬見えてしまうのが気になるところだが、コピーできるわけでもないので、まあこれはしょうがないと考えるしかないだろう。Sampleソースプログラム。対応のブラウザで見てください。【コラム】FederationとGlobalの違いGlobalは、アプリ内の連携という意味で使われることが多い。GAEでGlobalにアクセスできるものといえば、DatastoreやMemcacheなどがある。同じアプリであっても、内部変数などのLocalなリソースは1インスタンス内でしか利用できないが、Globalなリソースでは複数のインスタンス間で共有できる。(ちなみに、GAEでは異なるバージョンを10個持てるが、これらは1つのアプリとしてみなされるため、Globalなリソースを各々から参照できる。)ところが、アプリ(サイト)が異なれば、Globalなリソースであってもアクセスすることができない。Federationには「連携」という意味があり、サイトを跨ぐ連携という意味でよく用いられる。Docsとの連携なので、サイトを跨ぐFederationの仕組みが必要になる。Googleのログイン認証についてちょっと本題からずれるが、Googleのログイン認証についていろいろ調査したことをまとめてみる。(話が複雑になるのでOAuthやAuthSubの話は省略する。)ログイン画面からログインするユーザアプリが勝手に画面をカストマイズすることは(たぶん)できない。以下のように、Bloggerなどは、ServiceLoginBoxを呼び出すことで独自のログイン画面を表示しているが、GAEの場合はServiceLoginが呼び出されている。Blogger:https://www.google.com/accounts/ServiceLoginBox?service=blogger&continue=https://www.blogger.com/loginz%3Fd%3Dhttps%253A%252F%252Fwww.blogger.com%252Fstart%253Fhl%253Dja%26a%3DALL&passive=true&alinsu=1&aplinsu=1&alwf=true&skipvpage=true&rm=false&showra=1&fpui=2&naui=8GAE:https://www.google.com/a/virtual-tech.net/ServiceLogin?service=ah&passive=true&continue=http://XXXXXX/_ah/login%3Fcontinue%3Dhttp://XXXXXX&ltmpl=ga&ahname=YYYYY&sig=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxまた、Googleトークのようにユーザ認証なしに1クリックでGMAILボックスが開くような操作はブラウザからはできない。その理由は、ログイン画面には、GALXというソルトが埋め込まれており、表示されるたびに毎回生成されるからである。ソルト(塩)とは、ダイジェストを生成するときに含める乱数のことで、認証が成功して認証キーが生成されるまでセッションに含まれている。GALXはログイン画面を表示させないと取得できないので自動化は無理というもの。ちなみにGoogleトークではGALXを独自に生成しているっぽいが、これはGoogleだから成せる技である。認証キーの取得では、ログイン画面から以外に、ClientLoginサービスを呼び出す方法がある。Applicationsにあるように、USERIDなどをPOSTすることで、SID,LSID,Authといった認証キーを取得できるが、ブラウザから直接取得することはできない。auth=your-authentication-tokenをつけてGETすることができない。SID,LSIDをCookieにつけようと思ってもクロスドメインにひっかかるのでできない。(ブラウザからgoogle.comにアクセスしてセットしなければならない。)XHR(AJAX)を使ってやるのも同様の理由でできない。要するにClientLogin認証はブラウザからは使えないということ。ブラウザ以外であれば、いろいろやり方はあるようである。Sample(セキュリティ例外を認めて強制表示させてください)のなかでは、X-GOOGLE-TOKENを取得するというところで、上記と同じような処理を実装している。Docsにログインすることは難しくない。Docs(service=writely)のSIDを取得する必要がある。それは、以下のstatコマンドをGETリクエストしてあげればよい。Docsにアクセスできる。(シングルサインオン)例えば、以下のGETリクエストを実行すると実際にコンテンツをダウンロードできる。(idはドキュメントID。Docsの画面で共有にしてダウンロードすると確認できる)https://docs.google.com/uc?id=xxxxxxxxxxxxxxxxxxxxxxxxxxx&export=downloadちなみに、downloadに続けて.htmlとすると、ブラウザはhtmlとして判断するので表示できてしまう。JavaScriptも同様に動かすことができる。提供元が、docs.google.comからdoc-xx-xx-docs.googleusercontent.comに遷移しているので、setCookieなどを仕込んで悪さをしようと思っても無駄である。https://docs.google.com/uc?id=xxxxxxxxxxxxxxxxxxxxxxxxxxx&export=download.html以下は、ServiceLoginを実行してからダウンロードを実行する方法。遅いのであまりおすすめではない。https://www.google.com/a/virtual-tech.net/ServiceLogin?service=writely&passive=true&nui=1&continue=https%3A%2F%2Fdocs.google.com%2Fa%2Fvirtual-tech.net%2Fuc%3Fexport%3Ddownload%26id%3DxxxxxxxxxxxxxダウンロードはGAEを経由せずにできるようになったが、アップロードはブラウザからは無理のようである。何とかしたいけどよい方法はないだろうか。HeaderFireBug+FireCookieshin1ogawaさんからコメントをいただいたので追記:イマイチ目的がわからない。gmail.comドメインのAppengineアプリから、userdomain.comのDocsのリソースにアクセスしたいなら、OAuthで普通に可能だけど、それとはまた違うのかな。私もOAuthでやれるんじゃないかと思っていろいろ調べてみたのですがだめでした。OAuthと周辺技術の勉強会を見ると、GFCの仕組みを使えばできそうな雰囲気なのですが・・・。わかったら教えてください。<追記>ああ、shin1ogawaさんがいっていたのは、コンシューマとサービスプロバイダ間を2LeggedOAuthで繋ぐって話か。(こんなのあったのね。知らんかった)2LeggedOAuthはHMAC-SHA1を使った共通鍵認証みたいなので鍵の保持が必要だけど、”2LeggedOAuth”ってすごそうな名前なので、古臭いWSSEよりはいいかもしれない。ついでに調べておきます。APIの認証をどうすべきか考えている。次のようなケースをどうするか。「既存のWebサイトがあり、既にユーザIDとパスワードによる認証によって、ブラウザでデータを提供している。MVCモデルについて一言いっておくかなーんて、MVCを語れるほどの知識はないのだが、琴線に触れてしまったので、私なりに言いたいことを言うことにする。vol82のWebAPIデザインの鉄則」に触発されたので書こうと思う。commitが可能である。いうイベントが開催された。Google、Amazon、SalesForce、Microsoftの4強+Niftyの、豪華面子でタイトルの通りごった煮にふさわしい感じの内容となった。ガチンコでお願いします8月12日、OracleがGoogleに対して訴訟を起こした。Oracleの持つJavaの知的所有権(特許および著作権)を侵害していることが理由とのこと。この問題はよくわからないので自分なりに整理してみることにした。(ただし私は法律には素人で間違いも多いと思う。Application)でサーバサイドをどうすべきかについて述べたいと思う。今、MEANが注目されている。OutputStreamをInputStreamに変換するOutputStreamからInputStreamに変換するにはどうしたらいいか。Pipeを使ってもOutputStreamと互換性がないので簡単にはいかない。Docsにオンライン・ファイルストレージ機能を追加するという発表があった。お題は、「フロントエンドエンジニアが主役のBaaSを作った話」です。Analyticsを使ってウェブサイトのトラフィック情報を収集しています。詳しくは、プライバシーポリシーを参照してください。