LoginSignup
3
2

More than 3 years have passed since last update.

gRPCとFirebase Authenticationで認証処理

Posted at

はじめに

gRPCとFirebase Authenticationを使用したGoサーバでの認証処理のやり方を紹介します。認可処理についてはまた別記事で書く予定です。

Firebase Authentication

SDKの追加は以下のコマンドからできます。

go get firebase.google.com/go

Firebase Admin SDK for Go の初期化は以下を参考にします。
サーバーに Firebase Admin SDK を追加する

従来はoption.WithCredentialsFile()を使用した初期化が一般的だったようですが、GOOGLE_APPLICATION_CREDENTIALS 環境変数を使用する初期化を強くお勧めしているようです。

firebase.go
package middleware

import (
    "context"
    firebase "firebase.google.com/go"
    "firebase.google.com/go/auth"
)

type Firebase struct {
    Auth *auth.Client
}

func NewFirebase() (inst *Firebase, err error) {
    inst = new(Firebase)
    // GOOGLE_APPLICATION_CREDENTIALSで指定した認証情報ファイルを暗黙的に読み込む
    app, err := firebase.NewApp(context.Background(), nil)
    if err != nil {
        return
    }
    authInst, err := app.Auth(context.Background())
    if err != nil {
        return
    }

    inst.Auth = authInst
    return
}

認証処理

これは後から説明するgrpc_auth.UnaryServerInterceptorで引数に使用する認証メソッドを持つレシーバの定義です。先ほどのFirebaseをフィールドに持ちます。

package middleware

import (
    "context"
    grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
)

type Authentication struct {
    firebase Firebase
}

func NewAuthentication(firebase Firebase) *Authentication {
    authInst := new(Authentication)
    authInst.firebase = firebase
    return authInst
}

func (au *Authentication) Authenticate(ctx context.Context) (newCtx context.Context, err error) {

    idToken, err := grpc_auth.AuthFromMD(ctx, "bearer")

    // JWT の検証
    token, err := au.firebase.Auth.VerifyIDToken(context.Background(), idToken)
    if err != nil {
        return
    }
    // 引数のコンテキストにtokenというキーにJWTの情報を入れて返す
    newCtx = context.WithValue(ctx, "token", token.Claims)
    return
}

ちなみに、こちらの記事がわかりやすかったので参考として共有しておきます。Interceptorに関しての説明を読んでおくとこの後の処理の内容がスムーズにわかると思います。
gRPC-GoのMiddleware (Inerceptor) で認証/認可してみる

認証で使用するミドルウェアはGo gRPC Middlewareに定義してあるgrpc_authを使用します。

main.go
package main

import (
    grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
    grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
    "google.golang.org/grpc"
    "google.golang.org/grpc/reflection"
    "log"
    pb "my-project/grpc"
    "my-project/middleware"
    "net"
)

func main() {

    listenPort, err := net.Listen("tcp", ":800")
    if err != nil {
        log.Fatalln(err)
    }

    // Firebaseインスタンスを生成
    firebase, err := NewFirebase()
    if err != nil {
        log.Fatalln(err)
    }
    // Authenticationインスタンスを生成
    auth = *NewAuthentication(*firebase)

    // serverに認証設定を追加
    server := grpc.NewServer(
        grpc_middleware.WithUnaryServerChain(
            grpc_auth.UnaryServerInterceptor(auth),
        ),
        // Streamingを使用する場合は必要
        grpc_middleware.WithStreamServerChain(
            grpc_auth.StreamServerInterceptor(auth),
        ))

    pb.MyProjectServer(server, &handler)

    reflection.Register(server)

    if err := server.Serve(listenPort); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

まとめ

簡単なgRPCとFirebase Authenticationを使用したGoサーバでの認証処理のやり方でした。認可についても似たようにInterceptorで実装できるので、また別の記事で描こうと思います。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2