Help us understand the problem. What is going on with this article?

GolangでFirebase Admin SDKの認証周りを試しました

はじめに

k.s.ロジャースの西谷です。

担当のプロジェクトでFirebase Authenticationを使うことになりました。
社内で利用しているプロジェクトは多数あるのですが、私自身利用するのが初めてになります。
知見がほぼ無いため今回は実際に手を動かしてFirebase Authenticationを使ってみようと思います。

間違い等があれば、コメントにてご指摘頂けたらと思います。

環境構築

  1. Go言語の開発環境を構築します(こちらは他解説に任せます)
  2. go get firebase.google.com/goでSDKを導入します
  3. Firebaseのプロジェクトを作成します
  4. プロジェクトの設定から秘密鍵を生成します
    スクリーンショット 2019-10-16 0.52.11.png

  5. 秘密鍵はSDKで利用しますので保存します

Firebaseを使うための初期化

Firebase利用のための初期化です。以降の処理でapp, clientを利用します。

ctx := context.Background()

opt := option.WithCredentialsFile("secretkey.json")
app, err := firebase.NewApp(context.Background(), nil, opt)
if err != nil {
    log.Panic(fmt.Errorf("error initializing app: %v", err))
}

client, err := app.Auth(ctx)
if err != nil {
    log.Fatalf("error getting Auth client: %v\n", err)
}

ユーザのCRUD

サンプルコードはこちらでほぼ網羅されています。

本記事ではよく使う機能と実行結果について記載しようと思います。

ユーザ作成

サンプルのcreateUserを実行します。レスポンスのUserInfoに登録情報が入っています。

func createUser(ctx context.Context, client *auth.Client) *auth.UserRecord {
    params := (&auth.UserToCreate{}).
        Email("user@example.com").
        EmailVerified(false).
        PhoneNumber("+15555550100").
        Password("secretPassword").
        DisplayName("John Doe").
        PhotoURL("http://www.example.com/12345678/photo.png").
        Disabled(false)
    u, err := client.CreateUser(ctx, params)
    if err != nil {
        log.Fatalf("error creating user: %v\n", err)
    }
    log.Printf("Successfully created user: %#v\n", u.UserInfo)

    return u
}
result
2019/10/16 02:20:39 UserInfo: &auth.UserInfo{DisplayName:"John Doe", Email:"user@example.com", PhoneNumber:"+15555550100", PhotoURL:"http://www.example.com/12345678/photo.png", ProviderID:"firebase", UID:"nlF8TIkKwYg0upBbfdJ8dDVJtkJ3"}

ユーザ取得

UIDを入れるとユーザデータを取得できます。

func getUser(ctx context.Context, client *auth.Client, uid string) *auth.UserRecord {
    u, err := client.GetUser(ctx, uid)
    if err != nil {
        log.Fatalf("error getting user %s: %v\n", uid, err)
    }
    log.Printf("Successfully fetched user data: %#v\n", u.UserInfo)

    return u
}
result
2019/10/16 02:26:07 Successfully fetched user data: &auth.UserInfo{DisplayName:"John Doe", Email:"user@example.com", PhoneNumber:"+15555550100", PhotoURL:"http://www.example.com/12345678/photo.png", ProviderID:"firebase", UID:"nlF8TIkKwYg0upBbfdJ8dDVJtkJ3"}

getUserByEmailを使うことでメールアドレス検索も出来ます。

ユーザ更新

func updateUser(ctx context.Context, client *auth.Client, uid string) {
    params := (&auth.UserToUpdate{}).
        Email("updated@example.com").
        EmailVerified(true).
        PhoneNumber("+15555550100").
        Password("newPassword").
        DisplayName("John Doe").
        PhotoURL("http://www.example.com/12345678/photo.png").
        Disabled(true)
    u, err := client.UpdateUser(ctx, uid, params)
    if err != nil {
        log.Fatalf("error updating user: %v\n", err)
    }
    log.Printf("Successfully fetched user data: %#v\n", u.UserInfo)
}
result
2019/10/16 02:41:55 Successfully fetched user data: &auth.UserInfo{DisplayName:"John Doe", Email:"updated@example.com", PhoneNumber:"+15555550100", PhotoURL:"http://www.example.com/12345678/photo.png", ProviderID:"firebase", UID:"nlF8TIkKwYg0upBbfdJ8dDVJtkJ3"}

ユーザ削除

func deleteUser(ctx context.Context, client *auth.Client, uid string) {
    err := client.DeleteUser(ctx, uid)
    if err != nil {
        log.Fatalf("error deleting user: %v\n", err)
    }
    log.Printf("Successfully deleted user: %s\n", uid)
}
result
2019/10/16 02:49:28 Successfully deleted user: nlF8TIkKwYg0upBbfdJ8dDVJtkJ3

カスタムクレーム

ユーザにカスタムクレームを持たせる必要があったため、こちらも試しました。

func customClaimsSet(ctx context.Context, client *auth.Client, uid string) {
    claims := map[string]interface{}{"admin": true}
    err := client.SetCustomUserClaims(ctx, uid, claims)
    if err != nil {
        log.Fatalf("error setting custom claims %v\n", err)
    }
}

user.CustomClaims["admin"]でカスタムクレームを取得することが出来ます。

また、カスタムトークンにクレームを埋め込む場合は次のようにします。

func createCustomTokenWithClaims(ctx context.Context, client *auth.Client, uid string) string {
    claims := map[string]interface{}{
        "premiumAccount": true,
    }

    token, err := client.CustomTokenWithClaims(ctx, uid, claims)
    if err != nil {
        log.Fatalf("error minting custom token: %v\n", err)
    }

    log.Printf("Got custom token: %v\n", token)
    return token
}

実行後にJavaScriptから設定したクレームを確認できます。

firebase.auth().signInWithCustomToken(token)
.then( user => {
    firebase.auth().currentUser.getIdTokenResult().then((idTokenResult) => {
        console.log(idTokenResult.claims);
    })
});

おわりに

今回はFirebase Admin SDKの認証周りについて試しました。
他にも多数機能があり、今後使う機会も多くなると思うので次の機会に試せたらと思います。

間違い等あればご指摘頂けたらと思います。

Wantedlyでもブログ投稿してます

Techブログに加えて会社ブログなどもやっているので、気になった方はぜひ覗いてみてください。
https://www.wantedly.com/companies/ks-rogers

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away