make is.dev make it simple. development.
2024年8月20日

PHPでGoogleログイン

PHPでGoogleログインを実装する。

使用環境

・ PHP 8.2.9
・ google/apiclient (Composerでインストール)

手順の概要

  1. GCP(Google Cloud Platform)にプロジェクトを作成する
  2. OAuth同意画面を設定する
  3. 認証情報(OAuth2.0クライアントID)を登録する
  4. ログイン画面を用意する(SSL通信、及び、ドメインが必要 ※ドメインはlocalhost可)
  5. ログイン結果を受け取るPHPスクリプトを用意する

GCPにプロジェクトを作成する

GCP(Google Cloud Platform)にログインして、プロジェクトの選択プルダウンをクリック。

ダイアログが開いたら、「新しいプロジェクト」をクリック。

プロジェクト名を入力して「作成」を実行。
下図では例として「LoginSample」と入力。

OAuth同意画面を設定する

左上のハンバーガーメニューを開き、「APIとサービス」を選択。
続けて、「OAuth同意画面」を選択。

OAuth同意画面の設定画面が開いたら、User Type「外部」を選択して「作成」を実行。

続く設定画面にて、アプリ名、ユーザーサポートメール、デベロッパーの連絡先情報を入力する。
(他項目は任意なので必要に応じて設定)
入力したら「保存して次へ」を実行。

次の設定画面で、スコープを追加する。
まずは、「スコープを追加または削除」ボタンをクリックする。

開いた画面で、以下3つのスコープを選択して「更新」を実行。
元の画面に戻るので、「非機密のスコープ」に選択した3つが追加されていることを確認して「保存して次へ」。

続けてテストユーザーの設定画面に進むが、登録は不要。
そのまま「保存して次へ」を実行。

※以上で同意画面の設定は完了するが、公開ステータスがデフォルトで「テスト」になっている。
 本番利用する際は、これを「本番環境」に切り替える必要があるので注意。

認証情報を登録する

登録と言っているが、認証情報(OAuth2.0クライアントID)を作成・取得するのがゴール。

左上のハンバーガーメニューを開き、「APIとサービス」を選択。
続けて、「OAuth同意画面」を選択。

認証情報画面が開いたら、上部の「+認証情報を作成」内の「OAuthクライアントID」を選択。

作成画面が開いたら、以下を設定する。
アプリケーションの種類は「ウェブアプリケーション」を選択。
名前は識別用なので任意の名前を入力。

承認済みのJavaScript生成元のURIには、ログイン画面を設置するURIを設定する。
その際、「https://」が必須(http://で指定すると、後々ログイン画面でJavaScriptがエラーを吐く)。
また、IPでは指定出来ずドメインが必要(localhostは可)。
必要に応じてポート番号の指定まで指定。
ドメイン以下(例えば、login.phpなど)は不要。

承認済みのリダイレクトURIには、ログイン後の遷移先のURLを指定する。
こちらはドメイン以降も入力が必要。
ただし、今回の実装方法ではログイン画面でリダイレクト先URLを指定するので設定しなくても動く。

各設定が終わったら「作成」を実行。

作成が終わるとクライアントIDが発行されるので、これを控えておく。
(控えずに画面を閉じてしまった場合、後からでも画面を開けば確認出来る)

ログイン画面を用意する

ログイン画面用のHTMLファイルを用意し、WEBサーバに設置する。
※OAuthクライアントID発行の際に設定した「承認済みのJavaScript生成元」とログイン画面のURLが一致する必要があるので注意。

<html lang="ja">
<head></head>
<body>

<script src="https://accounts.google.com/gsi/client" async></script>

<div id="g_id_onload"
     data-client_id="[前項で控えたクライアントID]"
     data-context="signin"
     data-ux_mode="popup"
     data-login_uri="https://localhost:8888/auth.php"
     data-auto_prompt="false">
</div>

<div class="g_id_signin"
     data-type="standard"
     data-shape="pill"
     data-theme="outline"
     data-text="signin_with"
     data-size="large"
     data-logo_alignment="left">
</div>

</body>
</html>
login.html

必要なJSファイルはGoogle社が提供しているので、それを読み込む。(5行目)

ボタンの表示には上記2つの<div>を置くが、パラーメータの内2つは指定が必要。
data-client_idには、前項で控えたクライアントIDを記載する。
data-login_uriには、OAuthクライアントIDを発行する際に登録したリダイレクトURIを記載する。
(GCP側の設定ではなく、こちらの指定が実際使われる。なので、GCP側の設定は省略していても問題はない)

その他のパラメータはボタンの見た目など。
Googleが提供しているツールでHTMLを生成出来るので、こちらを使って取得したHTMLを貼るのが良い。
https://developers.google.com/identity/gsi/web/tools/configurator?hl=ja

ログイン画面を実際に開くと、下図のようなボタンが表示される。

※ボタンを表示した際にエラーが出ていないかブラウザの開発ツールで確認しておくこと。
 見た目上ボタンが出ているが、裏でエラーが出ていることがある。
 ・SSL通信になっていない
 ・ログイン画面のURLがOAuthクライアントIDを発行する際に登録したリダイレクトURIと一致しない
 ・パラメータ等に不備がある
 などが考えられる。

ログインのリダイレクト先を用意する

ログイン成功時のリダイレクト先を用意する。
ここはPHPで実装。

事前準備として、google/apiclientをComposerでインストールする。

composer require google/apiclient

ログイン結果を受け取るスクリプト例は以下のようなもの。

<?php 

require_once '../vendor/autoload.php';

$idToken = $_POST['credential'];

define( 'CLIENT_ID', '[前項で控えたクライアントID]' );

$client = new Google_Client( [ 'client_id' => CLIENT_ID ] ); 

$payload = $client->verifyIdToken( $idToken );

if ( $payload ) {
    var_dump( $payload );
} else {
    // Error
}
auth.php

Google認証が通ると、リダイレクト先に対してIDトークンがPOSTで送られてくる。
それとIDトークンを使ってユーザ情報を取得する。

上記で$payloadに含まれる情報は連想配列で以下のようになっている。

issトークンの発行者(または署名者)。
https://accounts.google.com で固定。
azpトークンの発行者。クライアントIDが入る。
audトークンの対象。クライアントIDが入る。
subGoogleアカウントのユニークなID
emailEmailアドレス
email_verifiedEmailの正誤確認。Googleの場合、true固定?
nbfnbf = not before。JWT が有効になるUnixエポック時刻
nameGoogleアカウントのユーザ名(姓+名)
pictureGoogleアカウントのアイコン画像
given_nameGoogleアカウントのユーザ名(名)
family_nameGoogleアカウントのユーザ名(姓)
iatトークンが発行されたUnixエポック時刻
expトークンの有効期限が切れるUnixエポック時刻
jtiGoogleログインごとに生成される一意のID

パラメータを受け取った後の処理としては、sub、email、name、picture、given_name、family_nameを使って初回ログイン時のユーザ登録を。
2回目以降のログインでは、subを使ってユーザを特定、認証する。
など。