OpauthでmixiとYConnect用のstrategyを作ってみた

こんばんは、ritouです。

PHPの話です。

この記事見てて思い出したのですが、
mixiへの認証を行ってくれる「OmniAuth-mixi」を公開しました - mixi engineer blog

OpauthっていうOmniAuthのPHP版みたいなのがあって、【実験的に】mixiYahoo! JAPANのYConnect用のstrategyを作ったりしたことを残しておきます。

Opauthとは

Inspired by OmniAuth for Ruby, Opauth provides a standardized method for PHP applications to interface with authentication providers.
Opauth as a framework provides a set of API that allows developers to create strategies that work in a predictable manner across PHP frameworks and applications.

Opauth – Multi-provider authentication framework for PHP

inspired by OmniAuth for Ruby.

PHPのいろんなフレームワークで使えるとありますが、個人的にはSession周りが不安です。
後で少し説明します。

mixi用のstrategy : opauth-mixi

GitHub - ritou/opauth-mixi: Mixi strategy for Opauth

既にいろんなstrategyが出ていましたので、OAuth 2.0を使っているGoogle/Github/Facebookあたりの内容を流用して微調整したら動きました。

認証のライブラリなので、次の3つの機能を実装すればいい感じです。

  • request() : Authorization Endpointへのリクエストを作る
  • oauth2callback() : Clientのredirect_uriの処理
  • userinfo() : People APIからプロフィール情報とって変数に格納

イメージをつかむためには動いてるのを見るのが早いですね。
READMEどおり導入できるので説明は省略します。
下記URLにアクセスするとmixi Graph APIのAuthorization Endpointにリダイレクトします。
http://www8322u.sakura.ne.jp/opauth/example/mixi
(Client登録時のredirect_urihttp://www8322u.sakura.ne.jp/opauth/example/mixi/oauth2callbackで登録しておきました。)

戻ってくるとPeople APIの一部を利用したユーザー情報が取れてますよっと。

Opauthのセッション周りの実装があやしいというか、あんまり気にされていない気がするのでstateパラメータのセット/チェックをしていません。$_SESSION使えばPlainなPHPでは動くんだろうけどフレームワークに対応できなそう。とはいえ、こうやって紹介するのであればCSRF対策が不十分って言われるより$_SESSION使うほうがいいのかな。OAuth 1.0でRequest Tokenとかを保存しないといけないTwitterのStrategyとかはつかってる気がします。悩みますね。

Yahoo! JAPANのYconnect用のstrategy : opauth-yahoojp

https://github.com/ritou/opauth-yahoojp

これは同じようにYConnect用に作ったもの。
ひたすらreplaceすれば動くかと思ったら1点問題発生。

Token EndpointでAuthorization HeaderにClient ID/SecretをBasic認証の形式でセットするところがあります。OpauthでもHeaderをサポートしてそうだったのでこんな感じで書きました。

            $options = array(
                'http' => array(
                    'header' => "Content-type: application/x-www-form-urlencoded\r\n".
                                "Authorization: Basic ".base64_encode($this->strategy['client_id'] . ':' . $this->strategy['client_secret'])
                )
            );

でも、動かしたら何も起こらない。
なぜかと思い、Opauth側の実装見たらこうなってました。

		$stream = array('http' => array(
			'method' => 'POST',
			'header' => "Content-type: application/x-www-form-urlencoded",
			'content' => $query
		));

		$stream = array_merge($options, $stream);

これ、$options['http']に値入ってても$stream['http']の値で上書かれてるのでは。。。
他のStrategyで使ってないのかなと思って確認したけど、使ってないっぽいので、直してPull Req→無視←イマココ。 (2013/1/10追記)開発者から反応があって、 array_merge_recursive でいけたのでそれで直してもらいました。

mixiのStrategy作ったときは勝手に見つけてOpauthのページに掲載してくれたのに!
(2013/1/10追記)Strategyのところに追記されました。 https://github.com/uzyn/opauth

-        $stream = array_merge($options, $stream);
-
+        if(isset($options['http'])){
+            $stream['http'] = array_merge($stream['http'], $options['http']);
+        }

とりあえず、yconnect版を使いたければこちらからどうぞ。
GitHub - ritou/opauth: Multi-provider authentication framework for PHP
あ、他の人のいじるのにmasterブランチにコミットしてた。まぁいっか。。。

ここから動作が確認できます。
http://www8322u.sakura.ne.jp/opauth/example/yahoojp

たくさんデータくださいしてるので気をつけてください。

気になるので時間があったらやるかもなこと

OpenID Connect用 Strategy

OAuth 2.0用のやつにDiscoveryとかDynamic Client Registrationあたりの機能を入れればいけるかなと。
毎回Registrationするとうざそうなので考えなければならないことはありそうです。

Session周りの拡張

stateパラメータをサポートしていない理由がこちらです。TwitterとかのStrategyで平気で$_SESSIONとか使ってるんですが、フレームワークによってSessionの扱いって別だと思うのです。なので、その違いを吸収するようなクラスをOpauthで持ってないとダメな気がしているのですが、まだCakePHPやCodeIgniterで試してないのでなんとも言えません。誰か試した人いますかね?

わりとテスト少ない

。。。

ところで、Opauthってどれだけ使われてんのかな。

まとめ

  • RubyのOmniAuthみたいなのがPHPにもある
  • OpauthのStrategy作った。YConnectのStrategy動かすためにはちょっと修正必要だった
  • Opauth自体に直したいこともあるんだけどしばらくやらなそう。

ではまた。