OAuth 2.0時代の署名つきリクエストとは

こんばんは、ritouです。

前回のmixiページアプリについてのエントリでOAuth 1.0の署名つきリクエストが使われていることに触れました。mixi Graph APIはOAuth 2.0対応してるのに、、、と少しモヤモヤしたので、まずはOpenSocialの新しいSpecのSigned Fetchの部分を見てみました。

http://opensocial-resources.googlecode.com/svn/spec/trunk/Core-Gadget.xml#SignedFetch

OpenSocialでは様々なリクエストが存在しますが、OAuth 2.0をサポートする宣言の通り、gadgets.io.AuthorizationTypeが"OAUTH2"の場合の定義が追加されています。ただし、"SIGNED"、つまり署名付きリクエストの部分はOAuth 1.0系のままでした。感覚的にはContainer側が両方サポートするのはしょうがないとしても、開発者がOAuth 1.0の署名検証をずっと実装し続ける必要があるのはちょっとつらいのかなとも思いました。

というわけで、OpenSocialの話はいったんおいておいて、今回はOAuth 2.0時代に署名付きリクエスト送ろうと思ったらどうすればいいのか?について調べました。
Client CredentialでAccess TokenとってMAC Authenticationを使ってリクエストに署名つける方法もありますが、まぁそれもちょっと大変ですし。

最近だと、Facebookの独自実装とOpenID Connectで似て非なる署名付きのリクエストというかパラメータ自体に署名をつけて送る方法が使われているので紹介します。

FacebookのSigned Request

使われどころはこんな感じですね。

  • アプリがfacebookの環境からロードされたとき
  • ユーザーがアプリを登録/削除したとき

このとき、以下のようなsigned_requestパラメータが指定されます。

vlXgu64BQGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso
.
eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsIjAiOiJwYXlsb2FkIn0

見やすいように改行されていますが、"."より前はSignature,後はBase64 URL EncodeされたJSONデータになります。

JSONデータの中身はこちら。

  • user
  • algorithm
  • issued_at
  • user_id
  • oauth_token
  • expires
  • app_data
  • page

サンプルではalgorithmがHMAC-SHA256で、Keyにはapp secret(client secret)が利用されているようです。RSAでSignature作りたい場合などはどうするのでしょうか・・・

次に、OpenID Connectで使われているJWTを見てみましょう。

OpenID Connect : JWT(JWS)を用いた署名つきパラメータ

OpenID Connectでは、通常のOAuth 2.0のAuthorization RequestにOpenID Connect独自のパラメータなどを追加するためにちょっと拡張します。その際に、リクエストの内容をJSONオブジェクトにして署名をつけた文字列を作成し、"request"パラメータとして送っています。

その時にJSONオブジェクトから作成された文字列をJWTと呼び、以下の仕様で定義されています。

バージョンが古いJWSを説明したエントリはこちらです。→ JSON Web Signatureの紹介 - r-weblife
ちょっと端折りますが、内容はこんな感じです。

  • Header, Payload, Signatureの3つで構成
  • HeaderはalgなどSignatureに必要な値が入ったJSONデータをBase64 URL Encodeしたもの
  • Payloadは送りたいJSONデータをBase64 URL Encodeしたもの
  • SignatureはHeaderで指定した内容で生成した署名をBase64 URL Encodeしたもの

似てますよね。自分がこっちよりの立場なこともありますが、facebookのやり方よりもこっちの方が汎用的な気がします(そうなるように設計されています)。

mixiのPlatformのようにOpenSocialに準拠しているようなところは別ですが、OAuth 2.0でAPIを提供しているようなところが署名付きのリクエストをやりとりしたいなーと思った場合はこちらのJWSを用いるのはいかがでしょうか?

このあたりは引き続きウォッチしていきたいと思います。
ではまた。