CodeIgniter A3MでGoogle APIを使って友達になろうとした方法とその結果





最近、 A3Mライブラリ(これはCodeIgniterのかなり一般的な認証ライブラリです)をGoogleを介したOAuth2認証のサポートに固定するタスクがありました。 それはすべて、数か月前に友人が私のところに来たという事実から始まりました。 彼は、CodeIgniterについて古くから誰かが書いたWebサイトを持っています。 当然、この誰かはすでに未知の方向に姿を消しています。



サイトは完全に機能しており、問題は発生していません。そのため、友人はスチームバスを浴びず、どこかで更新や(神の禁じられた)移行についても考えませんでした。



ある晴れた日、彼はGoogle経由でログインすると、次のようなメッセージが届くことを発見しました。



Googleアカウント用のOpenID 2.0は廃止されます。 OpenID 2.0はサポートされなくなりました。 アプリでOpenID 2.0を使用している場合、移行スケジュールに示されているように、2015年4月20日のシャットダウン日までにアプリを移行する必要があります。



私の友人は決してプログラマーではありませんでしたが、彼は何かがおかしいと感じ、私がこの問題を解決できることを望んで私に向き直りました。

彼はGoogle経由でログインしたサイトにかなり大きなユーザーのデータベースがあり、このビジネスが4月20日までに修正されないと、多くのユーザーが突然サイトにアクセスできなくなります。



「問題ではありません。修正してください」と私は言い、Google 移行マニュアルに乗り込みました。 初めて読んだ後、私はすべてが複雑であることに気づき、より簡単な方法を探すことにしました。 「それは論理的です」と私は思いました。「A3Mの作者は、GoogleがOpenID 2.0のサポートを停止していることを認識しており、すでにGitHubにパッチを公開しています。」 そして、著者は一般的に最新ですが、彼らは特にこれについて心配しています、彼らはそこに時間/欲望/何かを持っていません。



私はベータブランチに送られ、そこでA3MとHybridAuthの統合が完了しました 。これにより、 OAuth2を介した人類ログインのすべての問題が解決されるはずです。 私にとっては、もちろん、Googleを介したこの非常にブランチ的なログインは、さまざまな理由で全面的に拒否されました。 原則として、私は夜間デバッガーで座って動作させることができましたが、時間が経ち、4月20日は容赦なく近づいていたので、別のより効果的な方法を探すことにしました。



判明したように、Googleのスタッフは時間を無駄にせず、多かれ少なかれよく知られている言語で既製のクライアントAPIを既に持っています。 現在、A3Mをgoogle-api-php-clientに「導入」するだけです。



まあ、仕事のために。



最初に、Google API PHP Clientをダウンロードします。



git clone https://github.com/google/google-api-php-client
      
      





フォルダ全体をアプリケーション/ライブラリにコピーします。 すべてを美しくつなぐだけです。



では、 console.developers.google.comにアクセスしてください。 ここで、新しいプロジェクトを作成する必要があります。 その後、APIにアクセスして、Google + APIを見つけて有効にします。 次に、「資格情報」に進み、「新しいクライアントID」を作成します。 正しいリダイレクトURIとJavaScriptオリジンを指定する必要があります。 作成後、クライアントIDとクライアントシークレットを取得します。



実際のコード:

application / controllers / account / connect_google.phpに移動します。 まず、Google APIを接続します。 ライブラリへの絶対パスを指定することが重要です。そうしないと、コンポーザーは必要なコンポーネントをすべてロードできません。



 set_include_path ( get_include_path () . PATH_SEPARATOR . APPPATH .'application/libraries/google-api-php-client/src/Google' ); require_once APPPATH . "libraries/google-api-php-client/src/Google/autoload.php"; require APPPATH . "libraries/google-api-php-client/src/Google/Client.php"; require APPPATH . "libraries/google-api-php-client/src/Google/Service/Oauth2.php"; //    ,    Google API. $client = new Google_Client (); $client->setApplicationName ( "A3M with OAuth2 support" ); $client->setClientId ( $client_id ); $client->setClientSecret ( $client_secret ); $client->setRedirectUri ( $redirect_uri ); $client->addScope ( "email" ); $client->setOpenidRealm ( $redirect_uri ); //      OpenID 2.0
      
      





つまり、 openid_realmをリクエストすると、 openid_idが返されます。これは、CodeIgniterがデータベース内で一意のユーザーIDとして使用するものです。



ところで、興味深い点が1つあります。 (CodeIgniter Webサイトに)OpenID 2.0をサポートしている間にGoogle経由でログインしたユーザーの古いデータベースが既にある場合、OAuth2を介して認証を試みると、 おそらく完全に異なるopenid_idが取得されるため、データベースからユーザーを識別できません。



open_idが常に同じであるためには、リダイレクトURIは両方の場合で同一でなければなりません。

詳細については、こちらをご覧ください。

stackoverflow.com/a/23051643/524743

stackoverflow.com/q/29229204/524743



openid_idクライアントを取得する方法は次のとおりです。



 // This method extracts openID2 ID form id token for backward compatibility private function getOpenIDFromToken($client, $token) { $id_token = json_decode ( $token ); $ticket = $client->verifyIdToken ( $id_token->{'id_token'} ); if ($ticket) { $data = $ticket->getAttributes (); return $data ['payload'] ['openid_id']; // user ID } return false; }
      
      





認証プロセスを開始します。



 $objOAuthService = new Google_Service_Oauth2 ( $client ); if (! isset ( $authURL )) //         “Expired Token” unset ( $_SESSION ['access_token'] ); //       //       endpoint if (isset ( $_GET ['code'] )) { $client->authenticate ( $_GET ['code'] ); $_SESSION ['access_token'] = $client->getAccessToken (); header ( 'Location: ' . filter_var ( $redirect_uri, FILTER_SANITIZE_URL ) ); } //    ,  openid_id if (isset ( $_SESSION ['access_token'] ) && $_SESSION ['access_token']) { $client->setAccessToken ( $_SESSION ['access_token'] ); $openid_id = $this->getOpenIDFromToken ( $client, $client->getAccessToken () ); } //           if ($client->getAccessToken ()) { $userData = $objOAuthService->userinfo->get (); $data ['userData'] = $userData; $_SESSION ['access_token'] = $client->getAccessToken (); $openid_id = $this->getOpenIDFromToken ( $client, $client->getAccessToken () ); } //       ,    URI,     . else { $authUrl = $client->createAuthUrl (); $data ['authUrl'] = $authUrl; header ( 'Location:' . $authUrl ); die (); //      :) }
      
      





...

ユーザーのデータを受け取ったら、データベースにあるかどうかを確認し、ない場合は新しいレコードを作成します。



 if (! $this->authentication->is_signed_in ()) { if ($userData) { $email = $userData->getEmail (); $openid_google = array('fullname' => $userData->getName (), $openid_google 'gender' => $userData->getGender (), $openid_google 'language' => $userData->getLocale (), $openid_google 'firstname' => $userData->getGivenName (), // google only $openid_google 'lastname' => $userData->getFamilyName (), // google only ); } // Store user's google data in session $this->session->set_userdata ( 'connect_create', array ( array ( 'provider' => 'openid', 'provider_id' => isset ( $openid_id ) ? $openid_id : NULL, 'email' => isset ( $email ) ? $email : NULL ), $openid_google ) ); // Create a3m account redirect ( 'account/connect_create' );
      
      







できた! ユーザーはデータベース内にあり、認証は成功し、誰もが満足しています。



すべてのソースはこちらです。 ご質問がありましたら、お気軽にお問い合わせください。



All Articles