Google Developers Blog: Reminder to migrate to OAuth 2.0 or OpenID Connect
http://googledevelopers.blogspot.jp/2015/03/reminder-to-migrate-to-oauth-20-or.html
GoogleのOpenID 2.0がサポート終了します。OpenID Connectへの移行期限は2015/4/20です。 | 事務局ブログ | OpenID ファウンデーション・ジャパン
http://www.openid.or.jp/blog/2015/04/google.html
弊社が担当しているサービスにもGoogleのOpenIDを認証に使っていたものがあり、移行作業を行いました。その際のメモを記しておきます。
システム概要
・BtoCのWebサービス
・CakePHP2.x使用
・OpenIDによるGoogleログイン、TwitterとFacebookのOAuth認証によるログイン機能あり
OpenIDのログインは、LightOpenIDというライブラリで実装していました。
lightopenid – Lightweight OpenID library. – Google Project Hosting
http://code.google.com/p/lightopenid/
コンパクトで使いやすかったのですが、OpenID終了につき今後はメンテしませんとのこと。
調べてみてわかったのですが、OpenID Connectというのは技術的にはOpenIDの後継ではなくOAuth2.0と同じもので、OAuthのライブラリがそのまま使えるということのようです。
上記システムではTwitterやFacebookのOAuth認証が実装されており、Opauthというライブラリを使用していました。これがそのまま使えそうです。
Opauth – Multi-provider authentication framework for PHP
http://opauth.org/
OpauthはCakePHPのプラグイン化もされていて、これを使って実装していました。
uzyn/cakephp-opauth ・ GitHub
https://github.com/uzyn/cakephp-opauth
Opauthには各サービス用のストラテジーと呼ばれるパッケージがあり、Googleの場合は以下を入れることで対応できます。
opauth/google ・ GitHub
https://github.com/opauth/google
今回やることとしては、上記のプラグイン達を使い、GoogleのOAuth認証を実装して、呼び出す際scopeパラメータにopenidを追加することで、OpenIDのユーザーIDを取得するという事のようです。
詳しくは公式のドキュメントに書かれています。
Migrating from OpenID 2.0 to OpenID Connect – Google Identity Platform – Google Developers
https://developers.google.com/identity/protocols/OpenID2Migration
通常、公式ドキュメントは実装するにあたって必要十分であり見るべきなのですが、必要以上の情報が含まれていて冗長であることも多いです。
なので時間が限られている時には、どなたかが実際に実装された時のメモを見てやったりします。今回もそういうのを探してみた所、以下の記事が参考になりました。
Google アカウントの認証を OpenID から OpenID Connect に移行する方法 – WebOS Goodies
http://webos-goodies.jp/archives/how_to_migrate_from_openid_to_openid_connect.html
作業の流れとしては以下のように進めていきました。
Google Developers Consoleにログインしてプロジェクトを作成。
https://console.developers.google.com/project
↓
適当なプロジェクト名とプロジェクトIDを入力。どちらも日本語は使えません。プロジェクトIDは自分で入力するか自動生成が可能。
↓
プロジェクトを作るとしばらくして画面が切り替わるので、APIと認証 → 認証情報 → 新しいクライアントIDを作成。
↓
ウェブアプリケーション(デフォルト)を選択し、同意画面を設定を押して必要事項を入力。
↓
サイトのURLとログイン後のリダイレクトURLを入力。これでOAuthに必要なクライアントIDとクライアントシークレットが生成されます。
ここからPHPソースの作業。
クライアントIDとクライアントシークレットをopauthに渡すようにします。
Configure::write('Opauth.Strategy.Google', array( 'client_id' => 'YOUR CLIENT ID', 'client_secret' => 'YOUR CLIENT SECRET' ));
次にログインさせるURLをOpenID時のものからOpauthを呼び出すように変更します。今回の例では以下のようになりました。
/openid_login?url=https://www.google.com/accounts/o8/id
という感じだったのが
/opauth/google
のように変更。
次はscopeにopenidを追加する作業ですが、今回は手っ取り早くGoogleStrategy.phpを書き換えました。
元は
'scope' => 'https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email'だったのを
'scope' => 'openid profile email'に変更。openidの他に元々あったprofile、emailもアカウント情報の取得のために必要です。
h という書き方だとGoogle+を有効にしていないユーザーが認証できなくなるらしいので、下の書き方にしました。
次に、パラメータにopenid.realmを追加します。が、ここで.と_を間違えたり://を%3A%2F%2Fと書いてはいけなかったりでしばらくはまりました。正解の書き方は
'openid.realm' => 'http://' . env( 'HTTP_HOST' )でした。単に http://ドメイン で良いのですね。
ここは実際にアクセスするドメインと一致しないとログイン時エラーになります。クライアントIDを登録したドメインとも一致しないといけません。ちなみにエラー表示は親切ですぐ原因がわかるようになっていました。
ここまでやるとコールバック時にid_tokenが返ってくるようになりました。それを.(ピリオド)で分解してbase64_decodeすると
https://www.google.coc/accounts/o8/id?id=AItObwzwQrXIZrW8y_a7lSJzKXJFtgA0QHzXgTx
のような形でOpenIDのIDが取得できます。id=以降の文字列がこれまでのDBに保存されていたIDと同じなのでこれで照合・新IDに置換などしてやればいいことになります。
ちなみに、デコードするのにGoogleの関数を使うと有効性の検証も行ってくれるみたいですが手間の都合で今回はパスし、素のbase64_decodeを使いました。
google/google-api-php-client – GitHub
https://github.com/google/google-api-php-client
後日、これでも入れて試してみたいと思います。
今の所は以上の対応でOKですが、上記の方法でOpenIDのIDが取得できる機能も2017年に終了するそうです。なのでOpenIDでログインしていたユーザーは、それまでにサービスにログインする必要がありますね。