ランサーズ等のサービスを開発・運用する中で得た知識やノウハウを紹介しています。

Labels:  PHP, インターンシップ, ツール/ライブラリ 投稿者:kamiyagunji

GoogleOAuth2.0を使って、超簡単にユーザー情報を取得した話

ランサーズ Advent Calendar 2019 4日目の記事となります。

みなさんこんにちは。ランサーズでエンジニアとしてインターンをしている神谷(@Gunji Kamiya)です。

今回の記事では、タイトルにもある通り、GoogleOAuthを使った実装の話を書いていきたいと思います!

みなさんは「GoogleOAuth」という言葉を聞いたことあるでしょうか?

もしかしたら、耳にしたことがあるかもしれませんが、一応解説をしておくと。。

GoogleOAuthとは

GoogleOAuthとは、Googleのプラットフォームが提供しているOAuth認証のことです。

これにより、Googleが提供しているプラットフォーム上でユーザーの合意が簡単に取れ、セキュアにユーザーの権限などを受け渡しすることができます。

今回管理画面では、よりログインのスムーズに行うために、このGoogleOAuthを使って、ログイン機能を実装することになりました。

ランサーズの歴史を簡単に

ランサーズのメインプロダクトは、2008年12月にリリースされました。

それと同じ時期に管理画面も作られたようなので、もう10年以上の歴史があることになりますね。。

ユーザーが使っているメインプロダクトは、定期的にUIの変更があったりするのですが、管理画面は社内の人間しか使わないということもあり、当時のままです。

まさにThe 管理画面!!というイメージを想像してもらって大丈夫です(笑)

とはいえ、10年以上ランサーズの管理画面を支えてきたのは事実ですし、これからもずっと使われていく大切な一つのプロダクトです。

これから責任を持って、使いやすく、みんなから好かれるような管理画面にしてあげるからね(´∀`*)

GoogleOAuthには世界中に豊富なライブラリが存在

さて、Googleログイン機能実装に取り組んでいきたいところだったのですが、ここで問題が。。

「やり方がわからない!!」という問題です。

まあこれは、初心者や経験者関係なくあるものですよね。

誰にでも初めてはあるものですし、今のご時世、インターネットに検索キーワードを入れれば簡単に答えにたどり着くことができるはずです。

検索をしてみると、さすがGoogleですね。

たくさんのドキュメントが用意されていました!

ただほとんどすべてが英語ベース!!

よく考えてみれば当たり前なことなのですが、これも良い経験なので頑張ってやってみましょう!

ライブラリをインストール

まずは、GoogleOAuthの実装に必要なライブラリをインストールしていきます。

ランサーズでは、CakePHPというフレームワークを使っているので、Composer経由でインストールします。

Google-Api-PHP-Clientのインストール

$ composer require google/apiclient:"^2.*"

GoogleSDKのインストール

$ composer require google/cloud:"^0.*"

これらのライブラリをインストールすることで、Googleサービス内の情報にアクセスするための機能を入れることができます。

しかし、これだけでは動きません!!

これとは別に、ユーザーを識別するための認証情報が必要になります。

Google Developers Consoleにログインし、対象のプロジェクトから「認証情報を作成」を押してください。

プルダウンが表示されるので、「OAuthクライアントID」を選択し、名前や制限事項などを設定してください。

その後、認証情報をJSON形式でダウンロードできるので、それもしておきましょう!!

認証情報を設置

アプリケーション側から認証情報を利用するために、特定のディレクトリにJSONファイルを設置します。

僕はこんな感じでディレクトリにJSONファイルを設置しました。

 README.md
 bin
 composer.json
 composer.lock
 composer.phar
 config
  |-- adminlte.php
  |-- app.php
  |-- bootstrap.php
  |-- routes.php
  |-- google_client_secret.json ←←← Googleの認証情報を設置
 logs
 phpunit.xml.dist
 plugins
 src
 tests
 tmp
 vendor
 webroot

JSONファイルはわかりやすいようにリネームして使用すると良いと思います。

ちなみに認証情報は次のようなデータが入っています。

{
	"web": {
		"client_id": "********************************************.apps.googleusercontent.com",
		"project_id": "**************",
		"auth_uri": "https://accounts.google.com/o/oauth2/auth",
		"token_uri": "https://oauth2.googleapis.com/token",
		"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
		"client_secret": "************************"
	}
}

ログインアクション

ここからは実際にソースコードに記載する実装を書いていきます。

僕の場合は特定のメソッドにログインアクションを実装していきました。

それがこちらです↓


        // オブジェクトを生成
        $client = new Google_Client();

        // 認証情報が記載されているJSONファイルを読み込む(必須)
        $client->setAuthConfig(__DIR__ . '/../../config/google_client_secret.json');

        // リダイレクト先に `authGoogle`メソッドに指定(必須)
        $client->setRedirectUri('https://' . $_SERVER['HTTP_HOST'] . '/users/authGoogle');

        // アクセスのスコープを定義(必須)
        $client->addScope("https://www.googleapis.com/auth/userinfo.email");

        // ユーザーのオフライン時にアクセストークンを更新できるように指定(推奨)
        $client->setAccessType('offline');

        // アクセストークンの増分を許可(オプション)
        $client->setIncludeGrantedScopes(true);

ここでは、Google認証を行うために必要な設定をしています。

それぞれの細かい詳細はこちらを参考にしてください。
Google OAuth2.0

その後、Googleへログイン処理を行うための処理を実装していきます。

GoogleOAuthでは、リダイレクト時に正常なアクセスかどうかを判別するために、トークンを設定できます。

以下では、そういったセキュアな設定も行なっています。


        // 偽造防止のためにトークンを指定
        $state = substr(base_convert(hash('sha256', uniqid()), 16, 36), 0, 40);
        $session->write('google.stateToken', $state);
        $client->setState($state);

        // GoogleのOAuth2.0サーバーへリクエストを行うためのURLを生成する
        $auth_url = $client->createAuthUrl();
        header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));

Googleオブジェクトの凄いところなのですが、リクエストのためのURLなどの生成が非常に簡単にできるんですよね。

URLを格納した変数を確認してみると、きちんと設定した情報をもとに長いURLが生成されていました。

https://accounts.google.com/o/oauth2/auth?response_type=code&access_type=offline&client_id=********************************************.apps.googleusercontent.com&redirect_uri=https*******************.jp%2Fusers%2FauthGoogle&state=21awgk049068gcwkwcsokgk4okkgsowogwgckk8c&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&approval_prompt=auto&include_granted_scopes=true

これらの手順を踏むと、画面は勝手にGoogleログインのページへ遷移することになります。

コールバック先での処理

ここからはGoogleの認証画面を経て、コールバックしてきた先の処理を実装していきます。

先ほどにも書きましたが、ログインなどの処理は正常なリクエストかどうかをきちんと確認すべきなので、そういった点を考慮していきます。


        // 正常なリクエストではなかった場合の処理
        if ($_GET['state'] !== $session->read('google.stateToken')) {
            // Googleログインに失敗した場合は `/`にリダイレクトし、処理を終了させる
            $redirect_uri = 'https://' . $_SERVER['HTTP_HOST'] . '/';
            header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
            exit;
        }
        // 認証トークンを変数に格納
        $code = $_GET['code'];
        // 認証トークンを元にアクセストークンを生成
        $client->authenticate($code);
        // 後ほどユーザー情報を取得するためにセッションに保存
        $session->write('google.access', $client->getAccessToken());
        $redirect_uri = 'https://' . $_SERVER['HTTP_HOST'] . '/users/googleLogin';
        header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
        $client->setAccessToken($session->read('google.access.access_token'));

現在の状況は、アクセストークンを控えている状態です。

コメントにも記載されていますが、後ほどユーザー情報を取得するために、セッションにアクセストークンを保存します。

超簡単にユーザー情報を取得

さて、ここまで来ればあとはユーザー情報を取得するだけです。

タイトルにもある通り、超簡単に取得できるので、ご安心ください(笑)


        // アクセストークンをもとにGoogleのユーザーデータを取得
        $googleUser = json_decode(
            file_get_contents('https://www.googleapis.com/oauth2/v1/userinfo?' . 'access_token=' . $session->read('google.access.access_token'))
        );

これだけです!

この1行だけで、次のようなユーザー情報を取得することができるのです!

(
    [id] => 000000000000000000000
    [email] => test.lancers@lancers.co.jp
    [verified_email] => 1
    [name] => テスト ランサーズ
    [given_name] => ランサーズ
    [family_name] => テスト
    [picture] => https://sdl-stickershop.line.naver.jp/stickershop/v1/product/1348144/iphone/main@2x.png
    [locale] => ja
    [hd] => lancers.co.jp
)

あとはこれらの情報をもとにログイン処理をすれば、簡単にGoogleログイン機能を作ることができます!

まとめ

今回は、Googleのライブラリを使ってユーザー情報を超簡単に取得して見ました!

それによって、スムーズに管理画面へログインをすることができるようになりました。

英語ベースのドキュメントを読み解きながら実装していくのは大変でしたが、ものすごく良い経験になりました。

今後、そういった実装があったとしても、臆することなく、突き進んでいきたいと思います!

Advent Calendar 4日目でした!!(忘れてた笑)

Lancers(ランサーズ) Advent Calendar 2019

参考ソース

googleapis/google-api-php-client
Google | OAuth2

ランサーズではサービスを成長させてくれるエンジニア、デザイナーを募集しています!
ご興味がある方は、以下URLよりご応募ください。


【中途採用】
サービスリードエンジニア
テックリード(アーキテクト)
フロントエンドエンジニア
サーバーサイドエンジニア
業務エンジニア(社内システム基盤・基幹システム)

【インターン・学生バイト】
19新卒対象サマーインターン
エンジニアインターン

その他採用情報

関連記事

thumbnail
意外とすんなり作れたApple Watch 開発環境

  ランサーズ エンジニアの土屋です。 先日社内勉強会で行った、Apple Watch開発の環境構築内容を共有します。Apple Watch開発するぞ!という方のお役に立てたら幸いです。 Apple Watchについておさらい 2015/03/10の …

PHP5.3→5.6移行が完了しました

SREチームの金澤です。 PHP5.3→5.6バージョンアップが完了しましたので報告いたします。 CakePHP1.3→2.8バージョンアップが完了してから約2カ月での移行となりました。 2019/03/20にコネヒトさんで開催されたPHP勉強会で、その詳細に …

開発環境のDocker化

インフラエンジニアの金澤です。 今回、ランサーズの開発環境をDocker化しましたので、その内容を紹介いたします。 Docker移行の決断 Dockerについては、ここ1年で技術的な調査はしていましたが、決定的なメリットを見出していたわけではなく、採用に踏み切 …