Archive for the ‘OpenID’ Category

hetemlでPHP OpenID Libraryを使うときの注意事項(mixi.jpの場合)

というか、hetemlでOpenIDでmixiを使うときにdiscoverに失敗するって例なんだけどね。
CakePHPのexamplesにある「discover.php」を使っても「discoverに失敗したお」エラーが出るので確認はできると思います。
2010050202

なお、今回はこの場合が該当します。

※Symfonyに関しては同等のライブラリ提供は無さげなので今回は割愛です。
なお、symfonyでOpenIDを実装してみた | ueblogで実装されているようです。

まあ、ぶっちゃけ解決策は「証明書インストールしる!」ってことです。
○mixiでログインできない件
きさら’s – 利用報告(heteml)
○証明書インストールの方法(root権限がない場合)
mixi OpenIDのサンプルコードをPHP OpenID Libraryを使って動かしてみた(訂正) – 大阪 本町で働くソーシャルアプリ開発者 ダイアリー

Auth_Yadis_ParanoidHTTPFetcher#get関数と、Auth_Yadis_ParanoidHTTPFetcher#post関数でcurl_exec関数を実行する直前の、132行目と196行目に下記のコードを追記

このへんを参照しました。
(1)まず、https://mixi.jp/ にアクセスして、証明書を保存する。
(2)保存した証明書をサーバへUPする。
(3)Yadisのソースで、cURLでアクセスしてる部分でcURLオプション(CURLOPT_CAINFO) を変更する。
ソース変更点は、こういうかんじになります。

--- old/Auth/Yadis/ParanoidHTTPFetcher.php	2009-04-21 11:31:20.000000000 +0900
+++ new/Auth/Yadis/ParanoidHTTPFetcher.php	2010-05-02 16:14:15.000000000 +0900
@@ -128,6 +128,12 @@
             curl_setopt($c, CURLOPT_TIMEOUT, $off);
             curl_setopt($c, CURLOPT_URL, $url);
 
+            if ( $this->isHTTPS( $url )  && mb_ereg( "mixi\.jp" , $url ) ) {
+                curl_setopt( 
+                        $c , 
+                        CURLOPT_CAINFO ,
+                        '/home/sites/heteml/users***/*/*/*/*/ssl/mixi.jp.crt' ) ;
+            }
             curl_exec($c);
 
             $code = curl_getinfo($c, CURLINFO_HTTP_CODE);
@@ -191,6 +197,12 @@
         curl_setopt($c, CURLOPT_URL, $url);
         curl_setopt($c, CURLOPT_WRITEFUNCTION,
                     array(&$this, "_writeData"));
+            if ( $this->isHTTPS( $url )  && mb_ereg( "mixi\.jp" , $url ) ) {
+                curl_setopt( 
+                        $c , 
+                        CURLOPT_CAINFO ,
+                        '/home/sites/heteml/users***/*/*/*/*/*/ssl/mixi.jp.crt' ) ;
+            }
 
         curl_exec($c);

これで、さっくり動きました。
あ、/home/sites〜に関しては各自のホームディレクトリと証明書のある場所を指定してください。

なお、証明書に関する件はFAQにも述べられています

※追記
mixi.jp 以外の場合に挙動がおかしくなるのでなおしました。
証明書が「ない」OP毎にこの処理を追加してあげる必要があります。

Yahoo!JAPANのOpenIDが急に動かなくなった人へ

PerlでNet::OpenID::Consumer を使ってOpenIDの認証をしてるケースです。

つい先日あたりから(判明したのは今日)、

naive_verify_failed_return

を返してエラーになってしまいます。

なんでか、って延々と調べてたら・・・わかりました。
Need help deciphering this LiveJournal OpenID error

It comes from this line:

        return $self->_fail("naive_verify_failed_return") unless $args{'lifetime'};

So it did a dumb-mode (stateless) check_authentication request to your
server, but wasn’t able to find a “lifetime:\n” row where was
non-zero.

lifetimeがかえってないよー(または返すモードになってないよー)、ってかんじです。
Consumer.pmを再度確認。該当の記述はこちら。

        return $self->_fail("naive_verify_failed_return") unless
            $args{'is_valid'} eq "true" ||  # protocol 1.1
            $args{'lifetime'} > 0;          # DEPRECATED protocol 1.0

はい・・・そういうことです。

早い話が、ローカルに認証用のキャッシュ持たせないとだめっす。
というわけで、オブジェクト作ってるところでキャッシュを作るようにすればOK。

use CGI;
use LWP::UserAgent;
use Net::OpenID::Consumer;
use Cache::File ;

my $csr = Net::OpenID::Consumer->new(
  ua => LWP::UserAgent->new,
  cache => Cache::File->new( cache_root=>'/tmp/opicache',
                             default_expires=>'6000sec'      ) ,
  args => $query,
  consumer_secret => "hogehogehoge" ,
  required_root => "https://example.com/" ,
  minimum_version => 2.0
  );

参考:ソースから読むOpenID (1) – Yet Another Hackadelicなど

『docomo ID認証が怪しげすぎる件』が怪しすぎる件

なんというか、あきれる記事がまことしやかに信じられてて、げんなりなんだけど。
docomo ID認証が怪しげすぎる件 | [ bROOM.LOG ! ]
はてなブックマーク – docomo ID認証が怪しげすぎる件 | [ bROOM.LOG ! ]
本気でケータイサイト作ったことのある人間が読めば「ばっかじゃねーの」的レベルの記事です。
ところがブコメを見るとあまりに鵜呑みにしてるところが多いので、ちょいと軽くツッコミを入れておきます。

そのまえに、まずそれぞれの用語・機能について説明しないといけませんね。

●iモードID
端末(というよりは1契約単位)に与えられた固有のコード。
英数7文字、大文字/小文字の区別はあり。
ユーザ設定によって非通知にも設定可能(これはdocomo IDでの通知にも反映されます(後述))
なお、SSL通信では利用できません。
iモードIDについて(NTTドコモ)に説明があります。
英数7文字、大文字小文字区別ありということは、(10+26+26)^7通り、つまり3.52×10^12、unsignedで42bitで表せる情報(4.40×10^12)です。

●docomo ID
NTTドコモによるOpenID。OpenIDではOPに相当する。携帯電話との連携のために独自仕様が存在する。
なお、OP-local identifierはRP(OpenIDを利用する側)ごとに異なり、他のRPとの共用は出来ない。(仕様書3.7.2の(2)など)
docomo IDについて | NTTドコモ

●docomo ID の独自仕様
携帯電話との連携のために追加された独自仕様。
「ユーザ属性情報通知」(仕様書の3.8)、「ケータイ送信」(仕様書の4)の2つがある。
前者は、認証されたユーザのユーザーエージェント(User-Agentヘッダで送出される内容)とiモードIDを取得できる機能、後者は認証されたユーザに対して誘導先URLを(ユーザのメールアドレスを取得することなく)送信する機能。
正直、前者に関しては「これならSREGとか使えよ!」と思った程度にひどい(訂正)SREGだと「だだ漏れ」になっちゃうからマズいですよね。一応、OP-local identifierとresponse_nonceの両方が必要でなおかつ有効期限が設定されている(短い)ため、第三者から乗っ取りアクセスはほぼ不可能。
ケータイ送信は、OpenIDの機能を使ってない。docomo IDのサイトでログインセッションが有効なときのみ使用可能で、docomo IDのサイトでユーザーに対して「送信確認」を行わないと使用できない。

それでは、説明が終わったので、本題。

まずは私自身の持論。
iモードIDですが、そもそもこれをID+パスワードの代替として使うものではない、ってことです。だからこれを「かんたんログイン」として使うには危険ってこと。
「guid=ON」さえつければ取得できる情報なので、IPアドレスと同程度の情報、と考えてます。
ちなみに、iモードID送出をオフにした(iメニューから辿って設定できます)場合、docomo IDで取得しようとした場合、このようになります。
1つ前の記事で書いたサンプルを利用しました。)
2010031021
GUIDに「9999999」など、本来と違う値がかえってきます。

まず、そもそもの「iモードID抜き放題」の話。
42bitくらいの情報だったら、ブルートフォースアタックしちゃえばいいじゃん!
IPアドレス制限してないとこだったら、(げふんげふん(自主規制))
まぁ、docomo ID使って取得じゃ!とかそんなセコいことしなくても得られるしー。

そして。
「危ない」という事例で示してる例は、よく読むといづれも「docomo ID」とは直接関係しない事例。
つまり、アクセス元のIPアドレスをチェックしてない(つまり、本当にケータイかどうかをチェックしてない)サイトに対して、突破攻撃できちゃうよん、ってこと。
それ、全然iモードIDともdocomo IDとも関係ないじゃん。
iモードIDの取得?docomo IDなんか使わないで、ケータイ向け勝手サイト作ってケータイで直接アクセスさせたほうがよっぽど効率的に取得できますよー。うふふ。

さらに大きな間違いが1つ。

docomoからすれば、これだけ世に広まっているケータイ認証や決済をPCの世界にも広めたい意図なのだというのは容易に想像できる。

「オフィシャルの」決済系はケータイからじゃないと行えないです。
単刀直入に言うと、決済処理に入るには、iモードIDだけではなにもできません。
いったん、決済の確認ページに飛ばされて、暗証番号を要求されます。

なんというか。
docomo IDのシステム「だけ」を責めるのは根本的に間違ってるよ、ってことが言いたかったんです。

docomo ID の独自APIにアクセスする(1)

前回の続きです。
例によって?PHP OpenID Libraryのexampleを改造。

今回は、独自APIの1つ「ユーザ属性情報通知」(3.8)、これはiモードID(guid=ONにしたときにDCMGUIDヘッダで取得できる個体識別文字列)をとってくるAPIです。
なお、iモードIDに関しては以前書いたのでそちらを参照してください。

割と手抜きのコードですが、差分はだいたいこんなかんじ。

--- ../../../w/php-openid-2.1.3/examples/consumer/finish_auth.php       2009-04-22 03:31:20.000000000 +0900
+++ ./finish_auth.php   2010-03-10 18:29:39.000000000 +0900
@@ -38,6 +38,26 @@
             $success .= '  (XRI CanonicalID: '.$escaped_canonicalID.') ';
         }

+       // var_dump ($response->message->getArg('http://specs.openid.net/auth/2.0','response_nonce') ) ;
+       // var_dump ( $response->message ) ;
+       $response_nonce = $response->message->getArg('http://specs.openid.net/auth/2.0','response_nonce') ;
+
+       // call docomo original API
+       $success .= "<br />response_nonce:" . $response_nonce . "<br /><br />\n" ;
+       $apicall_url  = "https://i.mydocomo.com/api/imode/g-info?" ;
+       $apicall_url .= "ver=1.0&openid=" . urlencode( $openid ) ;
+       $apicall_url .= "&nonce=" . urlencode( $response_nonce ) ;
+       $apicall_url .= "&GUID=&UA=" ;
+       $cu = curl_init() ;
+       curl_setopt( $cu , CURLOPT_URL            , $apicall_url ) ;
+       curl_setopt( $cu , CURLOPT_RETURNTRANSFER , TRUE ) ;
+       $httpresult = curl_exec( $cu ) ;
+       $aline = explode( "\n" , $httpresult ) ;
+       $success .= "API RESULT:<br />\n" ;
+       foreach( $aline as $a ) {
+               $success .= $a . "<br />\n" ;
+       }
+
         $sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse($response);

         $sreg = $sreg_resp->contents();

実行するとこんなかんじになります。
2010031011

追記:docomo IDの実装をはじめ、なぜiモードID等の取得のみこのようなことをしてるかについて興味深い考察をしてるサイトがありましたので紹介。
docomoのOpenIDの実装周りについて – 金利0無利息キャッシング – キャッシングできます – subtech

PHP OpenID Library で RP Discovery要求対応の例

具体的に言うとdocomo IDのことなんですが(笑)
とりあえずわかったことなんでメモ。

OpenIDそのに関しては前書いたメモがあるんでそっち参照。
で、今回の件。docomo IDの場合、RP Discoveryするんで、TrustRoot のaddressに、Accept: application/xrds+xmlで要求かけてるんですよね。
だから、index.php で、Acceptを判定して、XRDSドキュメントを返してあげればOKです。

PHP OpenID Libraryのexampleだと、追加するコードはこうなります。

--- ../../../w/php-openid-2.1.3/examples/consumer/index.php	2009-04-22 03:31:20.000000000 +0900
+++ ./index.php	2010-03-10 10:10:52.000000000 +0900
@@ -2,6 +2,17 @@
 require_once "common.php";
 
 global $pape_policy_uris;
+
+if ( $_SERVER['HTTP_ACCEPT'] == "application/xrds+xml" ) {
+	// returns XRDS
+	header ( "Content-type: application/xrds+xml" ) ;
+	$fh = fopen( "yadis.xrdf" , "r" ) ;
+	while( !feof( $fh ) ) {
+	 	print fgets( $fh ) ;
+	}
+	fclose( $fh ) ;
+	exit() ;
+}
 ?>
 <html>
   <head><title>PHP OpenID Authentication Example</title></head>

そして、読み込んでるyadis.xrdfはこう。

<?xml version="1.0" encoding="UTF-8"?>
<xrds:XRDS xmlns:xrds="xri://$xrds" xmlns:openid="http://openid.net/xmlns/1.0" xmlns="xri://$xrd*($v*2.0)">
<XRD>
<Service priority="0">
<Type>http://specs.openid.net/auth/2.0/return_to</Type>
<URI>http://example.ne.jp:80/php-openid-2.1.3/examples/consumer/finish_auth.php</URI>
</Service>
</XRD>
</xrds:XRDS>

URIには、戻り先のURIを書いてねー。

もうちょっと、まともな書き方(XRDSを返す関数での書き方)があると思いますが、それはあとで調べて書くつもり。

なお、この件は、「docomo ID 認証 インターフェース仕様書」の「3.7.2 OP実装仕様」の表3.2にありるように、

RP Discoveryに失敗した場合、RPにはエラーは返却せず、エラー画面を返却し終了します。

と、なってます。だからいきなりこんな画面が出ます。
2010031001
無事成功するとこうなります。
2010031002
docomo ID 固有の実装・機能に関しては、のちほど書きたいと思います。

参考:RP Discovery対策 – Web Life!!! – Yahoo!ブログ

OpenID(2.0)に関するメモ

自分用メモを兼ねて。

●本家

●わからんとか言っててもはじまらんので流れだけまとめた。(JPEGファイル、手書き)

流れの説明で、振ってある番号は本家ドキュメントの「3.Protocol Overview」のそれぞれの節番号に対応しています。
なお、2.の「Discovery Information」で使用するYadisプロトコルに関しては割愛してます。

●そもそもの基本について。

●技術的に、参考になりそうなサイトとか

●OPの公式情報とか

PHP OpenID Library って便利なものがありましてね。・・・というわけで参考にさせていただいたサイト。