LoginSignup
11
7

More than 3 years have passed since last update.

Google Sign−In for Websites でページをまたいでサインイン・サインアウトを行うメモ

Posted at

ウェブアプリで Google Sign-In を使用して、ログインページ(login.html とか)でサインインしたはいいけど、別のページ(home.html とか)でサインアウトする方法で少し悩んだのでメモφ(・・。

背景

ログインしてくる Google のアカウントが本当に存在しているものであるかを確認したい、またメールアドレスの情報など欲しかったので、Google Sign-In を使用してみました。

iOS で Google 認証・認可の実装は行ったことはあったのですが、今回は Google の機能を使いたいというわけではなく、認可までは必要ないなと思ったので、Google Sign-In を採用しました。(アクセストークンやリフレッシュトークンのやり取りをしなくていいのでお手軽!)

加えて、Google Sign-In を実装しようとしているウェブアプリで、「場合によってアカウントを使い分ける人もいるだろうなー」と思い、サインアウトまで実装することにしました。

そして、今回作成したウェブアプリは、今時の SPA(シングルページアプリケーション)ではありません。ログインページ、リスト表示ページや管理ページが、HTMLファイルごとに分かれているという形になっています。

以上、背景をまとめると下記になります。

  • Google Sign-In で認証
  • サインインとサインアウトの機能
  • 複数ページのウェブアプリケーション

Google Sign-In の実装

基本的に用意されたチュートリアルを見ながら、実装すればできます。

下記リンクが、Google 公式のチュートリアルです。
Integrating Google Sign-In into your web app

チュートリアルに従って実装していきます。
まずは、GCP でプロジェクトの構成(チュートリアル上に設定箇所有り)を行い、ウェブアプリケーションの"CLIENT ID"を取得します。
Auth Client の選択は、"Web browser"(実装のやり方によって選ぶものは変わります。"Web Server"の場合、認証後、トークンをサーバーに送る形になります。)、Authorized Javascript Origin は、任意に設定します。
GCP のコンソールページで後から変更できるのでとりあえずは、Auth Client の"Web browser"と"があっていれば OK です。

続いて、サインインを実装する HTML ファイルの script タグに"Google Platform Library"を使うよと宣言。

login.html
<script src="https://apis.google.com/js/platform.js" async defer></script>

更に meta タグに、使用するのは"Google Sign-In"であるということを先程取得した"CLIENT ID"と交えてセットします(取得した"CLIENT ID"は、"YOUR_CLIENT_ID"部に代入)。

login.html
<meta name="google-signin-client_id" content="YOUR_CLIENT_ID.apps.googleusercontent.com">

そして、サインインボタンを置きたいところに"g-signin2"という class の div タグを挿入。

login.html
<div class="g-signin2" data-onsuccess="onSignIn"></div>

上記のように、class に"g-signin2"と書けば、勝手に Google のイイ感じのボタンが設置されます。自分好みにボタンの形を変えたい場合は、Building a custom Google Sign-In button を参照してコツコツやってね!とのことです。

上記 div タグを記述し、どんなものが出るのかなー?と、ローカル環境で確認しようと試しても、何も出てこないです。落ち着いてウェブ上で表示させましょう。

data-onsuccess 属性は、Google サインイン(認証まで)が行われるとセットした処理を行うというものです。上記の場合処理は、onSignIn 関数が実行されます。
ウェブアプリを開くブラウザで、既に Google サインインが完了した状態になっていた場合、ウェブページを読み込む際に、既に Google サインインが行われているものとして、セットした関数が実行されます。普段から Google アカウントを使用(Gmail や Google ドライブなどで)していると、最初からログインされた状態になっていて、なんで勝手にサインイン後の処理が実行されるんだ?となるので注意してください。

サインインの状態は、ボタン上の表示でわかります。"g-signin2"のボタンであれば下図のように、サインインされていない場合は「ログイン」と表示され、既にサインインされている場合は「Signed in」と表示されます。
Screen Shot 2019-07-16 at 14.16.09.png

最後に、サインアウトの実装です。

login.html
<a href="#" onclick="signOut();">Sign out</a>
<script>
  function signOut() {
    var auth2 = gapi.auth2.getAuthInstance();
    auth2.signOut().then(function () {
      console.log('User signed out.');
    });
  }
</script>

簡単ですね!

しかし、ここで困る。

上記のコードは、「サインインとサインアウトが同じHTMLファイルだった場合」の実装です。
例えば、サインインを「login.html」、サインアウトを「home.html」と分けて実装すると、上記コードのまま実装することはできません。上記コードだけで実装しようとすると、下記のエラーが発生します。

Uncaught ReferenceError: gapi is not defined

"gapi"が未定義と。。
script タグや meta タグは別のHTMLファイル「login.html」上で定義していることになるので、gapi が未定義なのもしかたないかーと思い、「home.html」にも同様の script タグと meta タグを追加。試してみたところ、今度は下記のエラーが発生。

Uncaught TypeError: Cannot read property 'getAuthInstance' of undefined

未定義の"getAuthInstance"プロパティが読めない。。
"getAuthInstance" ってどんなやつやねんということで、公式ドキュメントの Google Sign-In JavaScript client reference を参照にいきます。すると、気になる記述を発見。

このメソッドを呼び出す前に、gapi.auth2.init()でGoogleAuthオブジェクトを初期化する必要があります。
(日本語訳)

ぉ、おう。。。

色々ありましたが、正解は下記。

home.html
<a href="#" onclick="signOut();">Sign out</a>
<script>
  function signOut() {
    gapi.load('auth2', function () {
      gapi.auth2.init().then(function () {
        var auth2 = gapi.auth2.getAuthInstance()
        auth2.signOut().then(function () {
          console.log('User signed out.');
        });
      });
    });
  }
</script>

"auth2"をロードして、init して、認証インスタンスを取得し、それでサインアウトを行うようです。

正解のサインアウトの手順をまとめると、、

  1. script タグ、meta タグをサインアウトを実装する HTMLファイルに記述
  2. "auth2"を load
  3. GoogleAuth オブジェクト(gapi.auth2)を初期化(init)
  4. GoogleAuth オブジェクトで認証インスタンスを取得
  5. 取得した認証インスタンスに対してサインアウト

サインインしたのとは別の HTMLファイルでサインアウトをしようとすると1, 2, 3の手順を余計に行っておく必要があるようです。

まとめ

サインインとサインアウトを別々の HTMLファイルで実施する時は、サインアウト時に認証情報を取り直さないといけません。なのでそれぞれの HTMLファイルで Google Sign-In に関連した meta タグ、script タグを記載する必要があるようです。当然といえば当然の話でしたね。

以上、スタックオーバーフローで集めてきた情報をまとめたメモ書きでした。

11
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
7