I will show you how to process authentication on Go server using gRPC and Firebase Authentication. I will write about the authorization process in another article.
Firebase Authentication You can add the SDK from the following command.
go get firebase.google.com/go
Refer to the following for initializing the Firebase Admin SDK for Go. Add the Firebase Admin SDK to your server (https://firebase.google.com/docs/admin/setup?hl=ja#initialize_the_sdk)
In the past, it seems that initialization using ```option.WithCredentialsFile ()` `` was common, but it seems that initialization using the GOOGLE_APPLICATION_CREDENTIALS environment variable is strongly recommended.
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_Implicitly read the credential file specified by 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
}
This is the definition of a receiver that has an authentication method to use as an argument in grpc_auth.UnaryServerInterceptor
, which will be explained later. Have the Firebase in the field.
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 verification
token, err := au.firebase.Auth.VerifyIDToken(context.Background(), idToken)
if err != nil {
return
}
//Return JWT information in the key token in the context of the argument
newCtx = context.WithValue(ctx, "token", token.Claims)
return
}
By the way, this article was easy to understand, so I will share it as a reference. If you read the explanation about Interceptor, you can understand the contents of the subsequent processing smoothly. Try to authenticate / authorize with gRPC-Go Middleware (Inerceptor)
The middleware used for authentication uses grpc_auth as defined in Go gRPC Middleware.
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)
}
//Create a Firebase instance
firebase, err := NewFirebase()
if err != nil {
log.Fatalln(err)
}
//Create an Authentication instance
auth = *NewAuthentication(*firebase)
//Add authentication settings to server
server := grpc.NewServer(
grpc_middleware.WithUnaryServerChain(
grpc_auth.UnaryServerInterceptor(auth),
),
//Required when using 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)
}
}
It was a simple way to authenticate with a Go server using gRPC and Firebase Authentication. Authorization can be implemented in Interceptor in a similar way, so I'll draw it in another article.
Recommended Posts