はじめに
- Go と Angular で実装したクライアント・サーバーアプリケーションで Firebase Authentication を使ってログイン機能を実装します。
- また、実装したアプリを Google App Engine 環境へデプロイします。
手順概要
- Firebase Authentication の設定
- クライアントサイドのアプリケーションを作成
- サーバーサイドのアプリケーションを作成
- ローカル環境で実行して動作を確認
- Google App Engine 環境へデプロイして動作を確認
Firebase Authentication の設定
- Firebase Authentication を利用できるようにするため、Firebase のプロジェクトを作成し、Authentication の設定を行います
手順
- Firebase Console にログイン
- プロジェクトを作成
-
開発 > Authentication
に移動しログイン方法 > Google
で Google ログインを有効化 -
アプリを追加 > ウェブ
でウェブアプリを作成 - ウェブアプリ作成完了画面で表示される
apiKey
などの認証情報をメモしておく -
Authentication > ログイン方法
と移動しGoogle
のログインを有効にする
クライアントサイドのアプリケーションを作成
- Angular CLI でアプリケーションの雛形を作成し、Firebase Admin SDK を使った認証と、認証情報を使ったサーバーアプリケーションへのアクセスする機能を実装します。
アプリケーションの雛形の作成と SDK のインストール
# アプリケーションの作成
ng new gae-firebase-auth-sample-client
# SDK インストール
npm install firebase @angular/fire --save
Firebase 認証情報の設定
- Firebase のウェブアプリ作成時に表示された認証情報を設定ファイルに記述します
src/environments/environment.ts
export const environment = {
production: false,
firebase: {
apiKey: '<your-key>',
authDomain: '<your-project-authdomain>',
databaseURL: '<your-database-URL>',
projectId: '<your-project-id>',
storageBucket: '<your-storage-bucket>',
messagingSenderId: '<your-messaging-sender-id>'
}
};
Firebase Admin SDK の初期化
- Firebase Admin SDK を初期化し、Authentication や Http リクエスト用のモジュールを DI できるように読み込みます。
src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import {AngularFireModule} from '@angular/fire';
import { AngularFireAuthModule } from '@angular/fire/auth';
import {environment} from '../environments/environment';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
ログイン画面の実装
- ログイン画面とサーバーアプリケーションにアクセスする機能を実装します。
- ログイン処理は DI で初期化される AppComponent.afAuth によって管理され、未ログインならログインボタンを表示し、ログイン済みならログアウトボタンとサーバーへアクセスするボタンが表示されます。
- サーバーへのアクセス時には afAuth から取得できる ID トークンをヘッダに付与して認証を行います。
src/app/app.component.ts
import { Component } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import { auth } from 'firebase/app';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import {environment} from '../environments/environment';
@Component({
selector: 'app-root',
template: `
<div *ngIf="afAuth.user | async as user; else showLogin">
<h1>Hello {{ user.displayName }}!</h1>
<button (click)="logout()">Logout</button>
<button (click)="accessServer()">Access Server</button>
</div>
<ng-template #showLogin>
<p>Please login.</p>
<button (click)="login()">Login with Google</button>
</ng-template>
`,
})
export class AppComponent {
constructor(public afAuth: AngularFireAuth, private http: HttpClient) {
}
// Firebase Authentication のログイン実行
login() {
this.afAuth.auth.signInWithPopup(new auth.GoogleAuthProvider());
}
// Firebase Authentication のログアウト実行
logout() {
this.afAuth.auth.signOut();
}
// Firebase Authentication の ID Token をヘッダに付与してサーバーアクセスする
accessServer() {
this.afAuth.auth.currentUser.getIdToken().then((idToken: string) => {
const header = new HttpHeaders().set('Authorization', 'Bearer ' + idToken);
this.http.get(environment.serverUrl, {headers: header}).subscribe((res: string) => {
console.log(res);
});
});
}
}
サーバーサイドのアプリケーションを作成
- Go 1.12 で Firebase Authentication の ID トークンを受け取って検証を行うだけのサーバーアプリケーションを作成します
- 依存パッケージ管理は Go Modules を使用します
メインファイルの作成
- net/http を使って ID トークンを検証するだけの HTTP サーバーを実装します
- ローカル環境での実行時にはサーバーアプリケーションとクライアントアプリケーションが別ドメインになるため、環境変数で CORS を有効にできるように用意しておきます
app.go
package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"strings"
firebase "firebase.google.com/go"
"firebase.google.com/go/auth"
"github.com/rs/cors"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", top)
port := os.Getenv("PORT")
if port == "" {
port = "8080"
log.Printf("Defaulting to port %s", port)
}
addr := fmt.Sprintf(":%s", port)
if os.Getenv("ENABLE_CORS") != "" {
c := cors.New(cors.Options{
AllowedOrigins: []string{"http://localhost:4200"},
AllowedHeaders: []string{"Authorization"},
Debug: true,
})
log.Fatal(http.ListenAndServe(addr, c.Handler(mux)))
} else {
log.Fatal(http.ListenAndServe(addr, mux))
}
}
func top(w http.ResponseWriter, r *http.Request) {
// Firebase Auth クライアントの作成
ctx := r.Context()
client, err := newClient(ctx)
if err != nil {
log.Fatalf("error initializing app: %v\n", err)
}
// ヘッダから ID Token の取得
idToken := strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")
// ID Token の検証
token, err := client.VerifyIDToken(ctx, idToken)
if err != nil {
log.Fatalf("error verifying ID token: %v\n", err)
}
fmt.Fprintf(w, `{"result":"verified id token. %+v"}`, token)
}
func newClient(ctx context.Context) (*auth.Client, error) {
app, err := firebase.NewApp(ctx, nil)
if err != nil {
return nil, err
}
client, err := app.Auth(ctx)
if err != nil {
return nil, err
}
return client, err
}
依存パッケージの管理
- Go Modules を使って依存パッケージをダウンロードします
go mod init
go mod download
ローカル環境で実行して動作を確認
- クライアントアプリケーションとサーバーアプリケーションをそれぞれローカルで実行し、ログイン及びサーバーアクセスの動作確認を行います。
サーバーアプリケーションの実行
- サーバーアプリケーションをローカルで実行する際には Firebase へアクセスするためにサービスアカウントの秘密鍵を用意する必要があります
Firebase のサービスアカウントの秘密鍵のダウンロード
- Firebase Console にログイン
-
設定 > プロジェクトの設定
に移動しサービスアカウント > Firebase Admin SDK
を選択 -
新しい秘密鍵の作成
ボタン押下で JSON ファイルをダウンロード
実行
GOOGLE_APPLICATION_CREDENTIALS=${秘密鍵ファイルのパス} \
ENABLE_CORS=1 \
go run app.go
クライアントアプリケーションの実行
ng serve
動作確認
-
http://localhost:4200 へアクセスし
Login with Google
ボタンを押下すると Google 認証画面へリダイレクトされて認証が行われます - ログイン状態では
Logout
ボタンでログアウト処理がAccess Server
でサーバーアクセス処理が実行されます。サーバーアクセスの結果は Console で確認できます。 - Firebase Authentication による認証ができていると Firebase コンソールから作成済みユーザーの一覧も確認できます。
Google App Engine 環境へデプロイして動作を確認
クライアントアプリケーションのビルド
- クライアントアプリケーションをビルドしてサーバーアプリケーションはいかに出力し Google App Engine で配信できるようにする
ng build --prod --output-path=${PATH_TO_SERVER_APP}/client/ --base-href=/client/
サーバーアプリケーションの Google App Engine 設定
- Google App Engine 用の設定ファイル app.yaml を作成する
-
/client/
へのリクエストをクライアントアプリケーションのファイルで処理できるようにhandlers
設定を行います
app.yaml
runtime: go112
handlers:
- url: /client/(.*\.(gif|png|jpeg|jpg|css|js|ico))$
static_files: client/\1
upload: client/(.*)
- url: /client/(.*)
static_files: client/index.html
upload: client/index.html
- url: /.*
script: auto
Firebase Authentication 設定更新
- Firebase Authentication で Google App Engine のドメインから Google ログインができるように許可ドメインを追加します。
手順
- Firebase コンソールにログイン
-
Authentication > ログイン設定
に移動し -
承認済みドメイン
にプロジェクト名.appspot.com
を追加
デプロイ
gcloud app deploy
動作確認
- https://{プロジェクト名}.appsopt.com/client/ にアクセスしてローカル環境と同様に動作確認を行います
参考サイト
- https://github.com/angular/angularfire
- https://github.com/angular/angularfire/blob/master/docs/install-and-setup.md
- https://firebase.google.com/docs/admin/setup
- https://firebase.google.com/docs/auth/admin/verify-id-tokens