
最近、 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のスタッフは時間を無駄にせず、多かれ少なかれよく知られている言語で既製のクライアント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' );
できた! ユーザーはデータベース内にあり、認証は成功し、誰もが満足しています。
すべてのソースはこちらです。 ご質問がありましたら、お気軽にお問い合わせください。