さくっとDockerを使ってFirebase エミュレータのAuthenticationで認証を試す
はじめに
株式会社バニッシュ・スタンダードでエンジニアをしております、chanponと申します。最近、Firebaseを触る機会があり、Firebaseエミュレータの構築について学びましたので、その経験を共有したいと思います。この記事では、Dockerを使ってFirebaseエミュレータを立ち上げ、Authenticationを利用したユーザーの登録から認証までの流れを紹介します。
事前準備
まず、FirebaseエミュレータをDockerで動かすために必要なファイルを準備します。プロジェクトIDはexampleとします。
ファイル構成
firebase
├── .firebaserc
├── firebase.json
├── compose.yml
└── Dockerfile
.firebaserc
プロジェクトIDを指定します。
{
"projects": {
"default": "example"
}
}
firebase.json
使用するサービスを指定します。今回はAuthenticationとUIのみを使用します。
{
"emulators": {
"auth": {
"host": "0.0.0.0",
"port": 9099
},
"ui": {
"host": "0.0.0.0",
"port": 4000,
"enabled": true
},
"singleProjectMode": true
}
}
Dockerfile
Node.jsとFirebaseツールを含むDockerイメージを作成します。
FROM node:20.14.0-alpine3.20
# 必要なパッケージをインストール
RUN apk update \
&& apk --no-cache add openjdk17-jre-headless \
&& rm -rf /var/cache/apk/*
# Firebase CLIをインストール
RUN npm install -g firebase-tools
Docker Compose設定
前述のファイルをマウントしてDocker Composeを設定します。
services:
firebase:
container_name: 'firebase'
build:
context: ./
dockerfile: Dockerfile
volumes:
- ./firebase/.firebaserc:/opt/firebase/.firebaserc
- ./firebase/firebase.json:/opt/firebase/firebase.json
ports:
- 4000:4000
- 9099:9099
working_dir: /opt/firebase
command: firebase emulators:start --project example
tty: true
Firebaseエミュレータの立ち上げ
Docker Composeでエミュレータを立ち上げます。
docker compose up
エミュレータが立ち上がると、エミュレータの画面にアクセスできます。
エミュレータの管理画面にアクセスすると、以下のような画面が表示されます。
Firebaseエミュレータを使ったサンプルコード
以下にFirebase Admin Go SDKを使ったユーザー登録と認証の例を示します。
ユーザー登録
以下のコードは、定義した情報を使ってユーザーを登録します。
package main
import (
"context"
"log"
"os"
firebase "firebase.google.com/go/v4"
"firebase.google.com/go/v4/auth"
)
const (
projectID = "example"
email = "test@example.com"
password = "12345678"
uID = "test"
displayName = "test"
)
func main() {
// Firebaseエミュレータのホストを設定
os.Setenv("FIREBASE_AUTH_EMULATOR_HOST", "localhost:9099")
// コンテキストの作成
ctx := context.Background()
// Firebaseアプリの初期化
app, err := firebase.NewApp(ctx, &firebase.Config{
ProjectID: projectID,
})
if err != nil {
log.Fatalf("Firebaseアプリの初期化に失敗しました: %v", err)
}
// Firebase Authクライアントの作成
client, err := app.Auth(ctx)
if err != nil {
log.Fatalf("Firebase Authクライアントの作成に失敗しました: %v", err)
}
// ユーザー情報の設定
user := new(auth.UserToCreate).
DisplayName(displayName).
Email(email).
Password(password).
UID(uID)
// ユーザーの作成
record, err := client.CreateUser(ctx, user)
if err != nil {
log.Fatalf("ユーザーの作成に失敗しました: %v", err)
}
// 登録されたユーザー情報をログに出力
log.Printf("ユーザーが作成されました: %+v", record)
}
登録が完了すると、FirebaseエミュレータのAuthentication画面に登録したユーザーが表示されます。
ログイン
上記で登録したユーザー情報を使ってログインします。
Firebaseエミュレータでもapikeyを指定する必要がありますので、今回はdummy
を設定しています。
package main
import (
"bytes"
"context"
"encoding/json"
"errors"
"log"
"net/http"
"os"
firebase "firebase.google.com/go/v4"
)
type Login struct {
Email string `json:"email"`
Password string `json:"password"`
ReturnSecureToken bool `json:"returnSecureToken"`
}
const (
projectID = "example"
// Firebaseエミュレータの場合、keyには任意の値を設定
endpoint = "http://localhost:9099/identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=dummy"
email = "test@example.com"
password = "12345678"
)
func main() {
// Firebaseエミュレータのホストを設定
os.Setenv("FIREBASE_AUTH_EMULATOR_HOST", "localhost:9099")
// コンテキストの作成
ctx := context.Background()
// Firebaseアプリの初期化
app, err := firebase.NewApp(ctx, &firebase.Config{
ProjectID: projectID,
})
if err != nil {
log.Fatalf("Firebaseアプリの初期化に失敗しました: %v", err)
}
// Firebase Authクライアントの作成
client, err := app.Auth(ctx)
if err != nil {
log.Fatalf("Firebase Authクライアントの作成に失敗しました: %v", err)
}
// ログイン処理を実行しIDトークンを取得
idToken, err := login(ctx, email, password)
if err != nil {
log.Fatalf("ログインに失敗しました: %v", err)
}
// IDトークンを検証
token, err := client.VerifyIDToken(ctx, idToken)
if err != nil {
log.Fatalf("IDトークンの検証に失敗しました: %v", err)
}
// ログインユーザーのUIDをログに出力
log.Println("ログイン成功: UID =", token.UID)
}
// ログイン処理を行う関数
func login(ctx context.Context, email, password string) (string, error) {
// ログインリクエストのペイロードを作成
payload, err := json.Marshal(&Login{
Email: email,
Password: password,
ReturnSecureToken: true,
})
if err != nil {
return "", err
}
// ログインリクエストを作成
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, bytes.NewBuffer(payload))
if err != nil {
return "", err
}
req.Header.Set("Content-Type", "application/json")
// リクエストを送信
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
// レスポンスのデコード
var result map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return "", err
}
// IDトークンの取得
idToken, ok := result["idToken"].(string)
if !ok {
return "", errors.New("IDトークンが見つかりません")
}
return idToken, nil
}
まとめ
Firebaseエミュレータを使うことで、ローカル環境で簡単にFirebaseの機能を試すことができます。特に、エミュレータをDockerで立ち上げることで、環境構築が容易になり、チームメンバー間での共有もスムーズに行えます。今回はAuthentication機能を使った基本的なユーザー登録と認証の流れを紹介しました。エミュレータを活用して、他のFirebase機能もぜひ試してみてください。
Discussion