ユーザーの認証

ユーザーのログインフローを作成し、プロファイル情報を使用して、Firebase 認証を使用したパーソナライズされた機能をユーザーに提供します。

このページとサンプルは、ユーザーが投稿をアップロードできる簡単なブログ アプリケーションの学習用サンプルを拡張したものの一部です。Go プログラミング言語と基本的なウェブ開発に精通している方を対象として説明します。最初から開始するには、Go を使用したアプリのビルドをご覧ください。

料金

このチュートリアルの実行に伴う費用はありません。このサンプルアプリを実行するだけであれば、無料の割り当てを超過することはありません。

始める前に

Go を使用したアプリのビルドのガイドを読了している場合は、このセクションをスキップしてください。それ以外の場合は、次の手順を実行します。

  1. プロジェクトとアプリケーションの設定の「始める前に」に記載されている作業を行います。

  2. この例では、データの保存で説明している手順の結果として生成される gophers-4 サンプルにコードを追加します。

    gophers-4 サンプルとその依存関係をローカルマシンにダウンロードします。

    go get -u -d github.com/GoogleCloudPlatform/golang-samples/appengine/gophers/gophers-4/...
    
  3. gophers-4 ディレクトリに移動します。

    cd $GOPATH/src/github.com/GoogleCloudPlatform/golang-samples/appengine/gophers/gophers-4
    

アプリケーションを構造化する

このサンプル プロジェクトの構造は次のとおりです。

  • go-app/: プロジェクトのルート ディレクトリ。

    • app.yaml: App Engine アプリケーションの構成設定。
    • main.go: アプリケーション コード。
    • index.html: ホームページを表示するための HTML テンプレート。
    • static/: 静的ファイルを格納するディレクトリ。
      • style.css: HTML ファイルの外観をフォーマットするスタイルシート。
      • gcp-gopher.svg: Gopher イメージ。
      • index.js: Firebase 認証ユーザー インターフェースを設定し、認証リクエストを処理します。

プロジェクトへの Firebase の追加

FirebaseUI を構成してログイン プロバイダを有効にするには、次の手順に従います。

  1. firebase.google.com/go パッケージを更新するか、インストールします。

    go get -u firebase.google.com/go
    
  2. main.go のインポート リストに Firebase ライブラリを追加します。

    firebase "firebase.google.com/go"

  3. index.html への初期化スニペットの追加を含め、アプリに Firebase を追加するで説明している手順を完了します。

  4. ユーザーが利用できるよう、Firebase コンソールで認証用プロバイダを有効化するために、[Authentication] > [ログイン方法] をクリックします。その後、[ログイン プロバイダ] で、カーソルをプロバイダの上に移動し、鉛筆アイコンをクリックします。

    プロバイダにログイン

  5. [有効] ボタンを切り替え、サードパーティ ID プロバイダの場合は、プロバイダのデベロッパー サイトからプロバイダ ID とシークレットを入力します。Firebase ドキュメントの、FacebookTwitterGitHub ガイドの「始める前に」に、具体的な指示が記載されています。プロバイダを有効にしたら、[保存] をクリックします。

    有効ボタンの切り替え

  6. Firebase コンソールの同じページの [承認済みドメイン] で [ドメインを追加] をクリックし、App Engine でアプリのドメインを次の形式で入力します。

    [PROJECT_ID].appspot.com
    

    ドメイン名の前に http:// を付けないでください。

  7. main.go の変数リストに firebaseConfig 変数を追加し、Firebase コンソールで生成した初期化スニペットからのデータベース URL、プロジェクト ID、ストレージ バケット情報を更新します。

    var (
    	firebaseConfig = &firebase.Config{
    		DatabaseURL:   "https://console.firebase.google.com > Overview > Add Firebase to your web app",
    		ProjectID:     "https://console.firebase.google.com > Overview > Add Firebase to your web app",
    		StorageBucket: "https://console.firebase.google.com > Overview > Add Firebase to your web app",
    	}
    	indexTemplate = template.Must(template.ParseFiles("index.html"))
    )
    

    Config タイプは、新しい Firebase アプリケーションの初期化に使用される構成を表します。

  8. index.html のカスタマイズされた初期化スニペットの下にあるページの <head> タグに次のスクリプトと CSS ファイルを含めます。

    <script src="https://cdn.firebase.com/libs/firebaseui/2.6.2/firebaseui.js"></script>
    <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/2.6.2/firebaseui.css" />

  9. style.css ファイルに次のスタイルを追加して、ユーザーのログインの進行状況を表示します。

    div.mdl-progress::after {
      display: block;
      content: 'Authenticating...';
      margin: 30px auto;
      text-align: center;
    }

  10. 認証用に選択したプロバイダを含む index.html の本文に空の <div> タグを追加します。

    <div id="firebaseui-auth-container"></div>

  11. ユーザーがログインしていない場合は非表示になる、ユーザーのアカウント情報と [ログアウト] ボタンを表示するために、index.html の本文に別の <div> タグを追加します。

    <div id="sign-in"></div>
    <div>
      <span id="account-details"></span>
      <button id="sign-out" hidden=true>Sign Out</button>
    </div>

  12. <form> 要素に ID、非表示属性、トークン入力を追加します。

    <form id="post-form" action="/" method="post" hidden=true>
      <div>Message: <input name="message" value="{{.Message}}"></div>
      <input type="hidden" name="token" id="token">
      <input type="submit">
    </form>

ユーザーの認証

このアプリケーションでは、ユーザーが次のフローを辿って、ログインしてメッセージを投稿します。

  1. ユーザーがクリックして、特定のプロバイダにログインします。
  2. index.js コードが Firebase にログインするためのリクエストを送信します。
  3. Firebase がユーザー情報と ID トークンを送り返し、フォーム内のエントリとウェブページを更新し、現在ログインしているユーザーを表示します。
  4. その後で、ユーザーがメッセージを作成してその投稿をアプリケーションに送信します。投稿は、App Engine サーバーに送信されます。
  5. サーバーがフォームから ID トークンを取り出して Firebase に送信し、ID トークンに関連付けられたユーザー情報を受け取ります。
  6. Firebase がユーザー情報を App Engine サーバーに戻します。App Engine サーバーはユーザー情報と一緒に投稿を Cloud Datastore に保存します。

Firebase からのユーザー情報の取得

フロントエンドの JavaScript コードは、Firebase からユーザーのメール、名前、画像、添付されたトークンを取得します。悪意のあるユーザーがメッセージに添付されたユーザー情報を変更できないようにするために、トークンのみが投稿を使用して送信されます。トークンは、ユーザーを識別する安全な方法です。アプリケーション サーバーは、トークンを使用してユーザーの情報を取得します。

  1. プロジェクトの static フォルダで index.js を作成します。

  2. ユーザーがページを読み込むときのためにイベント リスナーを追加します。すべての JavaScript コードはこのイベント リスナー内にあります。

  3. [ログアウト] ボタンに、Firebase の signOut 関数を呼び出すハンドラを追加します。

  4. ユーザーに提供するプロバイダを選択して、FirebaseUI ログイン ウィジェットを構成します。これは、前に Firebase コンソールで指定した有効なログイン プロバイダのリストと一致する必要があります。

    // FirebaseUI config.
    var uiConfig = {
      signInSuccessUrl: '/',
      signInOptions: [
        // Leave the lines as is for the providers you want to offer your users.
        firebase.auth.GoogleAuthProvider.PROVIDER_ID,
        firebase.auth.FacebookAuthProvider.PROVIDER_ID,
        firebase.auth.TwitterAuthProvider.PROVIDER_ID,
        firebase.auth.GithubAuthProvider.PROVIDER_ID,
        firebase.auth.EmailAuthProvider.PROVIDER_ID,
        firebase.auth.PhoneAuthProvider.PROVIDER_ID
      ],
      // Terms of service url.
      tosUrl: '<your-tos-url>'
    };

  5. Firebase の onAuthStateChanged() リスナーを使用して認証リクエストを処理します。これは、ユーザーがログインまたはログアウトしたときにトリガーされます。

    firebase.auth().onAuthStateChanged(function (user) {
      if (user) {
        // User is signed in.
        document.getElementById('sign-out').hidden = false;
        document.getElementById('post-form').hidden = false;
        document.getElementById('account-details').textContent =
            'Signed in as ' + user.displayName + ' (' + user.email + ')';
        user.getIdToken().then(function (accessToken) {
          // Add the token to the post form. The user info will be extracted
          // from the token by the server.
          document.getElementById('token').value = accessToken;
        });
      } else {
        // User is signed out.
        // Initialize the FirebaseUI Widget using Firebase.
        var ui = new firebaseui.auth.AuthUI(firebase.auth());
        // Show the Firebase login button.
        ui.start('#firebaseui-auth-container', uiConfig);
        // Update the login state indicators.
        document.getElementById('sign-out').hidden = true;
        document.getElementById('post-form').hidden = true;
        document.getElementById('account-details').textContent = '';
      }
    }, function (error) {
      console.log(error);
      alert('Unable to log in: ' + error)
    });

    ユーザーがログインに成功すると、ユーザーを一意に識別する対応する ID トークンを Firebase が作成します。getIdToken 関数がクライアントから ID トークンを取得して、そのトークンを HTML フォームにアタッチします。

  6. index.html ファイルで、ページの <head> タグでスクリプト ファイルをリンクします。

    <script src="/static/index.js"></script>

サーバーでトークンを確認する

クライアントがサーバーデータにアクセスするには、トークンが Firebase によって署名されていることをサーバーが確認する必要があります。ログイン ID プロバイダごとに異なる一連のクレームが送信されますが、それぞれに少なくとも一意のユーザー ID を持つ 1 つのサブクレームと、アプリでユーザー エクスペリエンスをパーソナライズするために使用可能なプロファイル情報(名前やメールなど)を提供する 1 つのクレームが含まれています。

  1. main.go 内の Post データ構造に UserID string フィールドを追加します。

    type Post struct {
    	Author  string
    	UserID  string
    	Message string
    	Posted  time.Time
    }
    

  2. indexHandler 関数で、r.Method リクエストが POST であることを確認した後に Firebase Authentication などの Firebase サービスへのアクセスを提供する新しい Firebase アプリケーションを作成します。次に、Firebase ID トークンを確認して、HTTPS を使用して App Engine サーバーに現在ログインしているユーザーを特定します。

    message := r.FormValue("message")
    
    // Create a new Firebase App.
    app, err := firebase.NewApp(ctx, firebaseConfig)
    if err != nil {
    	params.Notice = "Couldn't authenticate. Try logging in again?"
    	params.Message = message // Preserve their message so they can try again.
    	indexTemplate.Execute(w, params)
    	return
    }
    // Create a new authenticator for the app.
    auth, err := app.Auth(ctx)
    if err != nil {
    	params.Notice = "Couldn't authenticate. Try logging in again?"
    	params.Message = message // Preserve their message so they can try again.
    	indexTemplate.Execute(w, params)
    	return
    }
    // Verify the token passed in by the user is valid.
    tok, err := auth.VerifyIDTokenAndCheckRevoked(ctx, r.FormValue("token"))
    if err != nil {
    	params.Notice = "Couldn't authenticate. Try logging in again?"
    	params.Message = message // Preserve their message so they can try again.
    	indexTemplate.Execute(w, params)
    	return
    }
    // Use the validated token to get the user's information.
    user, err := auth.GetUser(ctx, tok.UID)
    if err != nil {
    	params.Notice = "Couldn't authenticate. Try logging in again?"
    	params.Message = message // Preserve their message so they can try again.
    	indexTemplate.Execute(w, params)
    	return
    }
    

  3. ユーザーの情報から新しい UserID フィールドと Author フィールドを生成するように post 変数を更新します。

    post := Post{
    	UserID:  user.UID, // Include UserID in case Author isn't unique.
    	Author:  user.DisplayName,
    	Message: message,
    	Posted:  time.Now(),
    }

  4. メッセージを投稿するためにはログインが必要なため、main.go から次の行を削除します。

    if post.Author == "" {
      post.Author = "Anonymous Gopher"
    }
    

アプリケーションをローカルで実行する

Cloud SDK に含まれているローカル開発用サーバー(dev_appserver.py)でアプリケーションを実行し、テストします。

  1. 次のコマンドを使用して、アプリケーションの app.yaml が配置されているプロジェクトのルート ディレクトリから、ローカルの開発用サーバーを起動します。

    dev_appserver.py app.yaml
    

    ローカルの開発用サーバーが起動し、ポート 8080 でリクエストを待機します。問題が発生する場合は、ここをクリックしてください。

  2. ウェブブラウザで http://localhost:8080/ にアクセスしてアプリを表示します。

    完成版

ローカル開発サーバー(dev_appserver.py)の実行

ローカルの開発用サーバーを実行するには、ディレクトリをフルパスで指定して dev_appserver.py を実行するか、PATH 環境変数に dev_appserver.py を追加します。

  • 元の App Engine SDK をインストールした場合、ツールは次の場所に配置されています。

    [PATH_TO_APP_ENGINE_SDK]/dev_appserver.py
    
  • Google Cloud SDK をインストールした場合、ツールは次の場所に配置されています。

    [PATH_TO_CLOUD_SDK]/google-cloud-sdk/bin/dev_appserver.py
    

    ヒント: Google Cloud SDK ツールを PATH 環境変数に追加し、シェルでコマンドの補完を有効にするには、次のコマンドを実行します。

    [PATH_TO_CLOUD_SDK]/google-cloud-sdk/install.sh
    

ポート番号の変更方法など、ローカルの開発用サーバーの実行について詳しくは、ローカルの開発用サーバーのリファレンスをご覧ください。

コードを変更する

ローカルの開発用サーバーはプロジェクト ファイルの変更を監視しており、コードに変更が加えられると、アプリケーションを再コンパイルして再起動します。

  1. では試してみましょう。開発用サーバーを起動したまま、index.html を編集して、「The Gopher Network」を別の語句に変更してみます。

  2. http://localhost:8080/ を再読み込みして変更を確認します。

アプリケーションをデプロイする

app.yaml が配置されているプロジェクトのルート ディレクトリから以下のコマンドを実行して、App Engine にアプリケーションをデプロイします。

gcloud app deploy

アプリケーションを表示する

ブラウザを起動して http://[YOUR_PROJECT_ID].appspot.com でアプリケーションを表示するには、次のコマンドを実行します。

gcloud app browse

クリーンアップ

このチュートリアルで使用するリソースに対して Google Cloud Platform アカウントに課金されないようにするには、App Engine プロジェクトを削除する手順を実行します。

次のステップ

これで、Firebase 認証を使用してメールとパスワードでユーザーを認証可能なアプリケーションが構築されました。以下のページを参照して、他の機能をアプリケーションに追加する方法を学習してください。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Go の App Engine スタンダード環境