App Engine 上でFirebase Authenticationを用いたFirebase 認証チュートリアル(Windows10)

# Firebase でのユーザーの認証
サーバー側の認証を使用して、ユーザー認証情報の確認と保存を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/6cc259ee-d136-6752-265a-6693c6cd7583.png)


本記事は、次のページで紹介されているチュートリアルを実際に行った際の記録です。
https://cloud.google.com/appengine/docs/standard/python/authenticating-users-firebase-appengine?hl=ja

#チュートリアルの目標

- Firebase Authentication ユーザー インターフェースを構成する。
- Firebase ID トークンを取得し、サーバー側の認証を使用して検証する。
- ユーザー認証情報と関連データを Cloud Datastore に保存する。
- NDB クライアント ライブラリを使用してデータベースに問い合わせる。
- アプリを App Engine にデプロイする。

# 作成するアプリとその構成
Firenotes という名前のシンプルなメモ編集アプリケーションを作成します。このアプリケーションは、ユーザーのメモを個人用のノートブックに保存します。ノートブックはユーザーごとに保存され、各ユーザーの一意の Firebase Authentication ID によって識別されます。

次の図は、FrontendとBackend(Server)が相互に通信する方法、およびユーザー認証情報が Firebase からデータベースにどのように移動するかを示しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/2d531a91-5bbc-7cc8-7cda-c10e412d358e.png)

- Frontendは、ログイン ユーザー インターフェースを構成し、Firebase Authentication ID を取得します。また、認証状態の変化を処理し、ユーザーにメモを表示します。
- FirebaseUI は、ユーザー ログイン、複数のプロバイダの 1 つのアカウントへのリンク、パスワードの回復などを処理するオープンソースのドロップイン ソリューションです。認証のおすすめの方法を実装して、スムーズで安全なログイン方式を実現します。
- Backend(Server)は、ユーザーの認証状態を検証し、ユーザーのプロフィール情報およびメモを返します。
- このアプリケーションは、NDB クライアント ライブラリを使用してユーザー認証情報を Cloud Datastore に保存します。

# Firebaseの準備
Firebase コンソールで Firebase プロジェクトを作成（追加）し、Firebaseにアプリを追加します。
https://console.firebase.google.com/?hl=ja

## Firebase プロジェクトの作成

**1) プロジェクトを作成します。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/5e147840-26e4-df52-d35d-360df81a6a0d.png)

**2) プロジェクトに名前を付けます。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/d46b2460-fde9-0998-4681-2434ce024227.png)

```
my-firebase-auth
```

※ 下段に表示された プロジェクトIDを控えておいてください。

**3) Googleアナリティクスを有効にしたまま、続行します。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/4ef86eb9-834f-7580-f61d-63cd345d063b.png)

**4) 利用規約に同意し、プロジェクトを作成します。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/d73ee4ce-7fa8-6b21-be0e-80cfe7b76cff.png)

**5) 準備ができたら、続行します。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/d7a8e27f-8366-4bdf-f4c9-9f8d9a081f3f.png)

**6) 指定した名前のプロジェクトが作成されました。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/d4a9214a-fe9e-f452-9ba6-4cfc99a38ef5.png)

## ウェブアプリに Firebase を追加

**1) ウェブをクリックします。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/7800a5b7-0150-4c4f-0a84-621bd9e3daf1.png)

**2) アプリのニックネームを付けます。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/2b30419b-5df0-9e00-6cf6-40dabd2101b6.png)

```
FireNotes
```

**3) Firebase SDK の追加を確認し、Firebase コンソールへ戻ります。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/392fbb97-79c0-f869-d88b-441019a717e8.png)

## ログイン方法の有効化と設定
Firebase コンソールで、[Authentication]メニューで、[ログイン方法]タブを開き、それぞれのログインプロバイダーを編集して、有効化します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/b5a69c24-179a-63e2-c324-2895b5e846d0.png)


有効化する方法は、[「ねこの足跡R」さんのページ](https://blog.katsubemakito.net/)で詳しく紹介されています。

- Google → https://blog.katsubemakito.net/firebase/firebase-authentication-google-web1
- [Facebook](https://firebase.google.com/docs/auth/web/facebook-login?hl=ja) → - https://blog.katsubemakito.net/firebase/firebase-authentication-facebook-web1
- [Twitter](https://firebase.google.com/docs/auth/web/twitter-login?hl=ja) → https://blog.katsubemakito.net/firebase/firebase-authentication-twitter-web1
- [GitHub](https://firebase.google.com/docs/auth/web/github-auth?hl=ja) → https://blog.katsubemakito.net/firebase/firebase-authentication-github-web1
- e-mail → https://blog.katsubemakito.net/firebase/firebase-authentication-email-web1

Facebook、Twitter、GitHubの場合、それぞれに管理用のアカウントが必要ですので、ここでは、Googleとe-mailとを有効化します。

**1) Googleログインプロバイダーの設定**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/10fb0f56-f7d1-bfe6-7135-a4972b62ed37.png)

**2) e-mailログインプロバイダーの設定**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/57a9c05b-73c6-f6ec-d005-f1b0e5033be2.png)

## ドメイン追加

[ログイン方法]タブの下段にある「承認済みドメイン」で [ドメインの追加] をクリックし、App Engine のアプリのドメインを次の形式で入力します（控えておいたプロジェクト ID）。
※ Firebase コンソールで、[Project Overview]に右の歯車アイコンから[プロジェクトの設定]を開くとプロジェクト IDを参照することができます。

```
[PROJECT_ID].appspot.com
```

ドメイン名の前に http:// を付けないでください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/5a043ef2-d39b-5025-f231-9627fc6c21dc.png)

# サンプルアプリのクローン作成とFirebase追加

##サンプルアプリのクローン作成
Google Cloud SDK Shell（コマンドプロンプト）を開き、Cドライブに作業フォルダ(gcpsample)を作成し、移動します。

```
cd c:\
mkdir gcpsample
cd gcpsample
```

サンプル アプリケーション レポジトリをローカルマシンにクローン作成します。

```
git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
```

サンプルコードが含まれるディレクトリに移動します。

```
cd python-docs-samples/appengine/standard/firebase/firenotes
```

dirコマンドで、backendフォルダとfrontendフォルダとが配置されていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/205ba238-1b08-6609-c4c1-2f85a7d67dcf.png)

## 仮想環境の準備
virtualenvをインストールします。

```
py -3 -m pip install --upgrade virtualenv
```

次のコマンドで、virtualenvのバージョンを確認できます。

```
py -3 -m virtualenv --version
```

virtualenv がインストールされたら、プロジェクト内に仮想環境を作成できます。次の virtualenv により、venv フォルダに Python のインストール全体の仮想コピーを作成します。
※ Python 2.7をC:\Python27にインストールしている場合、つぎのようにpython.exeのパスを指定します。

```
py -3 -m virtualenv --python "C:\Python27\python.exe" venv
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/b2870357-c979-2955-c081-8d967efd95a0.png)

## Firebase をアプリに追加
Firebase コンソールで、[Project Overview]の右にある歯車アイコンから[プロジェクトの設定]を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/81c5ff1e-b4e3-f2ce-6dd4-b581135dd987.png)

**1) Firebaseの構成情報** 
frontend/main.js ファイルの次のセクションを入力します。
FirebaseコンソールのSettingページで、Firebase SDK snippetの欄に表示されているスニペットをコピー＆ペーストします（"構成"を選択してコピー）。

``` frontend/main.js
// Obtain the following from the "Add Firebase to your web app" dialogue
// Initialize Firebase
var config = {
  apiKey: "<API_KEY>",
  authDomain: "<PROJECT_ID>.firebaseapp.com",
  databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
  projectId: "<PROJECT_ID>",
  storageBucket: "<BUCKET>.appspot.com",
  messagingSenderId: "<MESSAGING_SENDER_ID>"
};
```

**2) Firebase ログイン ウィジェットの構成**
frontend/main.js ファイルで、ユーザーに提供するプロバイダを選択して FirebaseUI ログイン ウィジェットを構成します。

``` frontend/main.js
// Firebase log-in widget
function configureFirebaseLoginWidget() {
  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
    ],
    // Terms of service url
    'tosUrl': '<your-tos-url>',
  };

  var ui = new firebaseui.auth.AuthUI(firebase.auth());
  ui.start('#firebaseui-auth-container', uiConfig);
}
```

**3) 環境変数FIREBASE_PROJECT_IDの設定**
backend/app.yaml ファイルを編集し、FIREBASE_PROJECT_IDの値を、FirebaseコンソールのSetting画面に表示されている「プロジェクト ID」に置き換えます。

``` backend/app.yaml
runtime: python27
api_version: 1
threadsafe: true
service: backend

handlers:
- url: /.*
  script: main.app

env_variables:
  # Replace with your Firebase project ID.
  FIREBASE_PROJECT_ID: '<PROJECT_ID>'
```

# アプリケーションの動作環境設定

## 仮想環境の有効化
次のコマンドで、仮想環境を有効化して、Python の virtualenv のパスを shell に通します。

```
.\venv\Scripts\activate
```

仮想環境を有効化にすると、他のプロジェクトやグローバルの Python インストールに影響を与えずにパッケージをインストールできます。

## 依存関係のインストール
backend ディレクトリに移動して、依存関係をプロジェクトの lib ディレクトリにインストールします。

```
cd backend
pip install -t lib -r requirements.txt
```
appengine_config.py にある vendor.add() メソッドによってlib ディレクトリ内のライブラリが登録されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/c4fd1c46-e913-b0a6-7d61-c2b131a18656.png)

##アプリケーションをローカルで実行する
アプリケーションをローカルで実行するには、App Engine ローカル開発用サーバーを使用します。

frontend/main.js でbackendHostURLを次のURLに置き換えます。

```
http://localhost:8081
```

```frontend/main.js

$(function(){
  // This is the host for the backend.
  // TODO: When running Firenotes locally, set to http://localhost:8081. Before
  // deploying the application to a live production environment, change to
  // https://backend-dot-<PROJECT_ID>.appspot.com as specified in the
  // backend's app.yaml file.
  var backendHostUrl = 'http://localhost:8081';
```

アプリケーションのルート ディレクトリに移動します。その後で、開発用サーバーを始動します。

```
cd c:\gcpsample\python-docs-samples\appengine\standard\firebase\firenotes
dev_appserver.py frontend/app.yaml backend/app.yaml
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/e5f5ddc3-08a6-84a7-040e-f73711a24eb8.png)

ウェブブラウザで http://localhost:8080/ にアクセスし、ログインします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/707c220c-50f4-518c-3162-51e28ee3951c.png)

#アプリケーションのデプロイ
これで Firebase Authentication と App Engine アプリケーションが正常に統合されたことを確認できました。本番環境でアプリケーションを動作させるために、次の手順を実行します。

frontend/main.js のbackendHostURLを https://backend-dot-[PROJECT_ID].appspot.com に変更します。[PROJECT_ID] は実際のプロジェクト ID に置き換えてください。

```frontend/main.js

$(function(){
  // This is the host for the backend.
  // TODO: When running Firenotes locally, set to http://localhost:8081. Before
  // deploying the application to a live production environment, change to
  // https://backend-dot-<PROJECT_ID>.appspot.com as specified in the
  // backend's app.yaml file.
  var backendHostUrl = 'https://backend-dot-[PROJECT_ID].appspot.com';
```

Cloud SDK コマンドライン インターフェースを使用して、再初期化により、作成したFirebaseプロジェクトを選択し、アプリケーションをデプロイします。

```
gcloud init
gcloud app deploy backend/index.yaml frontend/app.yaml backend/app.yaml
```

https://[PROJECT_ID].appspot.com で実動しているアプリケーションを表示します。

#クリーンアップ
このチュートリアルで使用したリソースについて GCP アカウントに課金されないようにするには、App Engine プロジェクトを次の手順で削除することです。

1. GCP Console で [プロジェクト](https://console.cloud.google.com/cloud-resource-manager) ページに移動します。[→プロジェクト ページに移動](https://console.cloud.google.com/cloud-resource-manager)
1. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
1. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/d6bc7751-889e-804f-0cca-eeab7b81a7be.png)

# まとめ
- Firebaseのプロジェクトを作成しました。
- ログインプロバイダーの設定を行いました。
- サンプルソースコードのクローンを作成し、仮想環境下でローカル環境を構築しました。
- ローカル環境でアプリケーションを実行し、ログインしました。
- アプリケーションをデプロイしました。
- Firebaseプロジェクトを削除しました。

サンプルアプリのソースコードの詳細は、元のチュートリアルのページを参照してください。

- [サーバーでユーザーを認証する](https://cloud.google.com/appengine/docs/standard/python/authenticating-users-firebase-appengine#authenticating_users_on_the_server)
- [Cloud Datastore でのユーザーデータの管理](https://cloud.google.com/appengine/docs/standard/python/authenticating-users-firebase-appengine#managing-user-data-in-datastore)